package com.lancoo.ccas52.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lancoo.ccas52.entity.*;
import com.lancoo.ccas52.exception.BizException;
import com.lancoo.ccas52.mapper.*;
import com.lancoo.ccas52.pojo.common.PageInfo;
import com.lancoo.ccas52.pojo.constant.CommonConstants;
import com.lancoo.ccas52.pojo.constant.GlobalConstant;
import com.lancoo.ccas52.pojo.dto.*;
import com.lancoo.ccas52.pojo.response.basicPlatform.BaseGrade;
import com.lancoo.ccas52.pojo.vo.*;
import com.lancoo.ccas52.service.*;
import com.lancoo.ccas52.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 教学班 服务实现类
 * </p>
 *
 * @author quin.song
 * @since 2023-01-11
 */
@Service
@Slf4j
public class TeachingClassServiceImpl extends ServiceImpl<TeachingClassMapper, TeachingClass> implements TeachingClassService {

    @Resource
    private TeacherService teacherService;
    @Resource
    private TeachingClassWeekService teachingClassWeekService;
    @Resource
    @Lazy
    private YunBasicService yunBasicService;
    @Resource
    private TaskInfoService taskInfoService;
    @Resource
    private CourseService courseService;
    @Resource
    private SegmentService segmentService;
    @Resource
    private StudentService studentService;
    @Autowired
    private HttpServletRequest request;
    @Resource
    private CourseSettingService courseSettingService;
    @Resource
    private RoomService roomService;
    @Resource
    private MajorService majorService;


    @Resource
    private TeachingClassMapper teachingClassMapper;
    @Resource
    private TeachingClassStudentMapper teachingClassStudentMapper;
    @Resource
    private TeachingClassTeacherMapper teachingClassTeacherMapper;
    @Resource
    private ScheduleMapper scheduleMapper;
    @Resource
    private StudentMapper studentMapper;
    @Resource
    private RoomMapper roomMapper;
    @Resource
    private TeachingClassWeekMapper teachingClassWeekMapper;
    @Resource
    private SubClassMapper subClassMapper;
    @Resource
    private RoomTypeService roomTypeService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteClassRelated(List<Integer> taskId) {
        List<Long> teachingClassIds = teachingClassMapper.getClassIdsByTaskId(taskId);
        if (CollUtil.isNotEmpty(teachingClassIds)) {
            teachingClassStudentMapper.delete(new LambdaQueryWrapper<TeachingClassStudent>().in(TeachingClassStudent::getTeachingClassId, teachingClassIds));
            teachingClassTeacherMapper.delete(new LambdaQueryWrapper<TeachingClassTeacher>().in(TeachingClassTeacher::getTeachingClassId, teachingClassIds));
            teachingClassWeekService.remove(new LambdaQueryWrapper<TeachingClassWeek>().in(TeachingClassWeek::getTeachingClassId, teachingClassIds));
            this.remove(new LambdaQueryWrapper<TeachingClass>().in(TeachingClass::getTaskId, taskId));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer deleteClass(List<Long> teachingClassIds) {
        if (CollUtil.isNotEmpty(teachingClassIds)) {
            teachingClassStudentMapper.delete(new LambdaQueryWrapper<TeachingClassStudent>().in(TeachingClassStudent::getTeachingClassId, teachingClassIds));
            teachingClassTeacherMapper.delete(new LambdaQueryWrapper<TeachingClassTeacher>().in(TeachingClassTeacher::getTeachingClassId, teachingClassIds));
            teachingClassWeekService.remove(new LambdaQueryWrapper<TeachingClassWeek>().in(TeachingClassWeek::getTeachingClassId, teachingClassIds));
            this.removeBatchByIds(teachingClassIds);
        }
        return teachingClassIds.size();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<TeachingClass> addBatchTeachingClass(List<TeachingClassInput> list, Boolean isUpdate) {
        List<TeachingClass> teachingClassList = new ArrayList<>();
        //教学班对应教师
        List<TeachingClassTeacher> teachingClassTeacherList = new ArrayList<>();
        //教学班对应学生
        List<TeachingClassStudent> teachingClassStudentList = new ArrayList<>();
        for (TeachingClassInput teachingClassInput : list) {
            TeachingClass teachingClass = new TeachingClass();
            BeanUtil.copyProperties(teachingClassInput, teachingClass);
            teachingClassList.add(teachingClass);
        }
        this.saveBatch(teachingClassList);
        if (isUpdate) {
            //更新教学班名字
            teachingClassList.forEach(a -> a.setTeachingClassName(a.getTeachingClassName() + "-" + a.getTeachingClassId()));
            this.updateBatchById(teachingClassList);
        }
        courseService.initTeachingClassWeek(teachingClassList);
        Map<String, Long> courseToTeachingClass = teachingClassList.stream().collect(Collectors.toMap(TeachingClass::getTeachingClassName, TeachingClass::getTeachingClassId));
        //构建教学班-学生-教师实体类
        list.forEach(a -> {
            if (CollUtil.isNotEmpty(a.getTeacherIds())) {
                a.getTeacherIds().forEach(teacherId ->
                {
                    //前端处理不规范，过滤掉教师id为null的数据
                    if (ObjUtil.isNotNull(teacherId.getTeacherId())) {
                        teachingClassTeacherList.add(new TeachingClassTeacher()
                                .setTeachingClassId(courseToTeachingClass.get(a.getTeachingClassName()))
                                .setTeacherId(teacherId.getTeacherId())
                                .setHourType(teacherId.getHourType())
                                .setTeacherType(0));
                    }
                });
            }

            if (CollUtil.isNotEmpty(a.getStudentIds())) {
                a.getStudentIds().forEach(studentId -> teachingClassStudentList.add(new TeachingClassStudent()
                        .setTeachingClassId(courseToTeachingClass.get(a.getTeachingClassName()))
                        .setStudentId(studentId)
                        .setFlag(1)));
            }
        });
        if (CollUtil.isNotEmpty(teachingClassTeacherList)) {
            teachingClassTeacherMapper.addBatch(teachingClassTeacherList);
        }
        //批量插入教学班学生，大数据批量插入
        Consumer<List<TeachingClassStudent>> studentConsumer = o -> teachingClassStudentMapper.addBatch(o);
        BatchInsert.batchSplitInsert(teachingClassStudentList, studentConsumer);
        return teachingClassList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public List<TeachingClass> addBatchTeachingClassV2(String schoolId, String term,List<TeachingClassInput> list, Boolean isUpdate) {
        List<TeachingClass> teachingClassList = new ArrayList<>();
        //教学班对应教师
        List<TeachingClassTeacher> teachingClassTeacherList = new ArrayList<>();
        //教学班对应学生
        List<TeachingClassStudent> teachingClassStudentList = new ArrayList<>();
        for (TeachingClassInput teachingClassInput : list) {
            TeachingClass teachingClass = new TeachingClass();
            BeanUtil.copyProperties(teachingClassInput, teachingClass);
            teachingClassList.add(teachingClass);
        }
        this.saveBatch(teachingClassList);
        if (isUpdate) {
            //更新教学班名字
            teachingClassList.forEach(a -> a.setTeachingClassName(a.getTeachingClassName() + "-" + a.getTeachingClassId()));
            this.updateBatchById(teachingClassList);
        }
        courseService.initTeachingClassWeek(teachingClassList);
        Map<String, Long> courseToTeachingClass = teachingClassList.stream().collect(Collectors.toMap(TeachingClass::getTeachingClassName, TeachingClass::getTeachingClassId));
        //构建教学班-学生-教师实体类
//        List<Teacher> teacherAll = teacherService.lambdaQuery().eq(Teacher::getSchoolId, schoolId)
//                .eq(Teacher::getTerm, term).list();
//        List<String> baseAll = teacherAll.stream().map(Teacher::getBaseTeacherId).collect(Collectors.toList());
//        Map<String, Long> allTeacherMap = teacherAll.stream().collect(Collectors.toMap(Teacher::getBaseTeacherId, Teacher::getTeacherId));

        for (TeachingClassInput a : list) {
            if (CollUtil.isNotEmpty(a.getTeacherIds())) {
                //构建教学班-学生-教师实体类
                List<Teacher> teacherAll = teacherService.lambdaQuery().eq(Teacher::getSchoolId, schoolId)
                        .eq(Teacher::getTerm, term).list();
                List<String> baseAll = teacherAll.stream().map(Teacher::getBaseTeacherId).collect(Collectors.toList());
                Map<String, Long> allTeacherMap = teacherAll.stream().collect(Collectors.toMap(Teacher::getBaseTeacherId, Teacher::getTeacherId));

                List<TeachingClassTeacher> teacherIds = a.getTeacherIds().stream().filter(o -> StrUtil.isNotEmpty(o.getBaseTeacherId())).collect(Collectors.toList());
                List<TeachingClassTeacher> add = teacherIds.stream().filter(o -> !baseAll.contains(o.getBaseTeacherId())).collect(Collectors.toList());
                List<Teacher> addTeacher = new ArrayList<>();
                add.forEach(o -> addTeacher.add(new Teacher()
                        .setTeacherName(o.getTeacherName())
                        .setBaseTeacherId(o.getBaseTeacherId())
                        .setIsEnable(1)
                        .setSchoolId(schoolId)
                        .setTerm(term)
                        .setImageUrl(o.getImageUrl())
                        .setHourType(o.getHourType())
                ));
                if (CollUtil.isNotEmpty(addTeacher)){
                    teacherService.saveBatch(addTeacher);
                    Map<String, Long> addTeacherMap = addTeacher.stream().collect(Collectors.toMap(Teacher::getBaseTeacherId, Teacher::getTeacherId));
                    addTeacher.forEach(teacherId -> {
                        //前端处理不规范，过滤掉教师id为null的数据
                        if (ObjUtil.isNotNull(teacherId.getTeacherId())) {
                            teachingClassTeacherList.add(new TeachingClassTeacher()
                                    .setTeachingClassId(courseToTeachingClass.get(a.getTeachingClassName()))
                                    .setTeacherId(addTeacherMap.get(teacherId.getBaseTeacherId()))
                                    .setHourType(teacherId.getHourType())
                                    .setTeacherType(0));
                        }
                    });
                }
                List<TeachingClassTeacher> exist = teacherIds.stream().filter(o -> baseAll.contains(o.getBaseTeacherId())).collect(Collectors.toList());
                exist.forEach(teacherId ->
                {
                    //前端处理不规范，过滤掉教师id为null的数据
                    if (ObjUtil.isNotNull(teacherId.getBaseTeacherId())) {
                        teachingClassTeacherList.add(new TeachingClassTeacher()
                                .setTeachingClassId(courseToTeachingClass.get(a.getTeachingClassName()))
                                .setTeacherId(allTeacherMap.get(teacherId.getBaseTeacherId()))
                                .setHourType(teacherId.getHourType())
                                .setTeacherType(0));
                    }
                });
            }

            if (CollUtil.isNotEmpty(a.getStudentIds())) {
                a.getStudentIds().forEach(studentId -> teachingClassStudentList.add(new TeachingClassStudent()
                        .setTeachingClassId(courseToTeachingClass.get(a.getTeachingClassName()))
                        .setStudentId(studentId)
                        .setFlag(1)));
            }
        }

        if (CollUtil.isNotEmpty(teachingClassTeacherList)) {
            teachingClassTeacherMapper.addBatch(teachingClassTeacherList);
        }
        //批量插入教学班学生，大数据批量插入
        Consumer<List<TeachingClassStudent>> studentConsumer = o -> teachingClassStudentMapper.addBatch(o);
        BatchInsert.batchSplitInsert(teachingClassStudentList, studentConsumer);
        return teachingClassList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TeachingClass updateTeachingClassV2(String schoolId, String term,TeachingClassInput teachingClassInput) {
        //教学班对应教师
        List<TeachingClassTeacher> teachingClassTeacherList = new ArrayList<>();
        //教学班对应学生
        List<TeachingClassStudent> teachingClassStudentList = new ArrayList<>();
        teachingClassStudentMapper.delete(new LambdaQueryWrapper<TeachingClassStudent>().eq(TeachingClassStudent::getTeachingClassId, teachingClassInput.getTeachingClassId()));
        teachingClassTeacherMapper.delete(new LambdaQueryWrapper<TeachingClassTeacher>().eq(TeachingClassTeacher::getTeachingClassId, teachingClassInput.getTeachingClassId()));
        TeachingClass teachingClass = new TeachingClass();
        BeanUtil.copyProperties(teachingClassInput, teachingClass);
        this.updateById(teachingClass);

//        List<Teacher> teacherAll = teacherService.lambdaQuery().eq(Teacher::getSchoolId, schoolId)
//                .eq(Teacher::getTerm, term).list();
//        List<String> baseAll = teacherAll.stream().map(Teacher::getBaseTeacherId).collect(Collectors.toList());
//        Map<String, Long> allTeacherMap = teacherAll.stream().collect(Collectors.toMap(Teacher::getBaseTeacherId, Teacher::getTeacherId));


        if (CollUtil.isNotEmpty(teachingClassInput.getTeacherIds())) {
            teachingClassInput.getTeacherIds().forEach(teacherId ->
            {
                List<Teacher> teacherAll = teacherService.lambdaQuery().eq(Teacher::getSchoolId, schoolId)
                        .eq(Teacher::getTerm, term).list();
                List<String> baseAll = teacherAll.stream().map(Teacher::getBaseTeacherId).collect(Collectors.toList());
                Map<String, Long> allTeacherMap = teacherAll.stream().collect(Collectors.toMap(Teacher::getBaseTeacherId, Teacher::getTeacherId));

                if (ObjUtil.isNotNull(teacherId.getBaseTeacherId())) {
                    if (!allTeacherMap.containsKey(teacherId.getBaseTeacherId())){
                        Teacher teacher = new Teacher().setTeacherName(teacherId.getTeacherName())
                                .setBaseTeacherId(teacherId.getBaseTeacherId())
                                .setIsEnable(1)
                                .setSchoolId(schoolId)
                                .setTerm(term)
                                .setImageUrl(teacherId.getImageUrl())
                                .setHourType(teacherId.getHourType());
                        teacherService.save(teacher);
                        teachingClassTeacherList.add(new TeachingClassTeacher()
                                .setTeachingClassId(teachingClassInput.getTeachingClassId())
                                .setTeacherId(teacher.getTeacherId())
                                .setHourType(teacherId.getHourType())
                                .setTeacherType(0));
                    }else {
                        teachingClassTeacherList.add(new TeachingClassTeacher()
                                .setTeachingClassId(teachingClassInput.getTeachingClassId())
                                .setTeacherId(allTeacherMap.get(teacherId.getBaseTeacherId()))
                                .setHourType(teacherId.getHourType())
                                .setTeacherType(0));
                    }
                }
            });
        }

        if (CollUtil.isNotEmpty(teachingClassInput.getStudentIds())) {
            teachingClassInput.getStudentIds().forEach(studentId -> teachingClassStudentList.add(new TeachingClassStudent()
                    .setTeachingClassId(teachingClass.getTeachingClassId())
                    .setStudentId(studentId)
                    .setFlag(1)));
        }
        if (CollUtil.isNotEmpty(teachingClassTeacherList)) {
            teachingClassTeacherMapper.addBatch(teachingClassTeacherList);
        }
        //批量插入教学班学生，大数据批量插入
        Consumer<List<TeachingClassStudent>> studentConsumer = o -> teachingClassStudentMapper.addBatch(o);
        BatchInsert.batchSplitInsert(teachingClassStudentList, studentConsumer);
        return teachingClass;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TeachingClass updateTeachingClass(TeachingClassInput teachingClassInput) {
        //教学班对应教师
        List<TeachingClassTeacher> teachingClassTeacherList = new ArrayList<>();
        //教学班对应学生
        List<TeachingClassStudent> teachingClassStudentList = new ArrayList<>();
        teachingClassStudentMapper.delete(new LambdaQueryWrapper<TeachingClassStudent>().eq(TeachingClassStudent::getTeachingClassId, teachingClassInput.getTeachingClassId()));
        teachingClassTeacherMapper.delete(new LambdaQueryWrapper<TeachingClassTeacher>().eq(TeachingClassTeacher::getTeachingClassId, teachingClassInput.getTeachingClassId()));
        TeachingClass teachingClass = new TeachingClass();
        BeanUtil.copyProperties(teachingClassInput, teachingClass);
        this.updateById(teachingClass);
        if (CollUtil.isNotEmpty(teachingClassInput.getTeacherIds())) {
            teachingClassInput.getTeacherIds().forEach(teacherId ->
                    {
                        if (ObjUtil.isNotNull(teacherId.getTeacherId())) {
                            teachingClassTeacherList.add(new TeachingClassTeacher()
                                    .setTeachingClassId(teachingClassInput.getTeachingClassId())
                                    .setTeacherId(teacherId.getTeacherId())
                                    .setHourType(teacherId.getHourType())
                                    .setTeacherType(0));
                        }
                    });
        }

        if (CollUtil.isNotEmpty(teachingClassInput.getStudentIds())) {
            teachingClassInput.getStudentIds().forEach(studentId -> teachingClassStudentList.add(new TeachingClassStudent()
                    .setTeachingClassId(teachingClass.getTeachingClassId())
                    .setStudentId(studentId)
                    .setFlag(1)));
        }
        if (CollUtil.isNotEmpty(teachingClassTeacherList)) {
            teachingClassTeacherMapper.addBatch(teachingClassTeacherList);
        }
        //批量插入教学班学生，大数据批量插入
        Consumer<List<TeachingClassStudent>> studentConsumer = o -> teachingClassStudentMapper.addBatch(o);
        BatchInsert.batchSplitInsert(teachingClassStudentList, studentConsumer);
        return teachingClass;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized List<TeachingClass> ensureTeachingClass(String schoolId, String term, List<TeachingClassInput> list) {
        /*
        确定教学班设置
        1：新增教学班 判断教学班名是否重复  添加学生教师信息
        2：更新教学班 获取教学班名，id不一样教学班名一样时为重复  先删除再添加学生教师信息
        3：删除教学班  根据教学班id删除教学班学生教师信息
         */
        List<TeachingClassInput> addLists = list.stream().filter(a -> a.getOperateType().equals(1)).collect(Collectors.toList());
        List<TeachingClassInput> updateLists = list.stream().filter(a -> a.getOperateType().equals(2)).collect(Collectors.toList());
        List<TeachingClassInput> removeLists = list.stream().filter(a -> a.getOperateType().equals(3)).collect(Collectors.toList());
        List<TeachingClassInput> updateBaseLists = list.stream().filter(a -> a.getOperateType().equals(4)).collect(Collectors.toList());


        StringJoiner sameName = new StringJoiner(",");
        //判断列表是否重复
        list.stream().filter(a -> !a.getOperateType().equals(3))
                .collect(Collectors.groupingBy(TeachingClassInput::getTeachingClassName, Collectors.counting()))
                .entrySet().stream()
                .filter(a -> a.getValue() > 1)
                .forEach(a -> sameName.add(a.getKey()));
        if (StrUtil.isNotEmpty(sameName.toString())) {
            throw new BizException(EnumResultCode.DATA_DUPLICATION.getCode(), "输入教学班列表名存在重复：" + sameName);
        }

        //todo 如果新增的教学班名字和删除的教学班名字相同，则将新增教学班改为更新教学班，并将教学班id赋值给新增教学班

        //判断数据库是否存在重名教学班
        List<String> isTeachingClassName = list.stream()
                .filter(a -> !a.getOperateType().equals(3) && !removeLists.stream().map(TeachingClassInput::getTeachingClassName).collect(Collectors.toList()).contains(a.getTeachingClassName()))
                .map(TeachingClassInput::getTeachingClassName).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(isTeachingClassName)) {
            List<Integer> taskIds = taskInfoService.lambdaQuery().eq(TaskInfo::getSchoolId, schoolId).eq(TaskInfo::getTerm, term).list()
                    .stream().map(TaskInfo::getTaskId).collect(Collectors.toList());
            List<TeachingClass> teachingClassList = this.lambdaQuery().in(TeachingClass::getTaskId, taskIds).in(TeachingClass::getTeachingClassName, isTeachingClassName).ne(TeachingClass::getTeachingClassType, 3).list();
            teachingClassList.forEach(a -> {
                list.forEach(b -> {
                    if (a.getTeachingClassName().equals(b.getTeachingClassName()) && !a.getTeachingClassId().equals(b.getTeachingClassId())) {
                        sameName.add(a.getTeachingClassName());
                    }
                });
            });
            if (StrUtil.isNotEmpty(sameName.toString())) {
                throw new BizException(EnumResultCode.DATA_DUPLICATION.getCode(), "教学班名重复：" + sameName);
            }
        }

        //入库
        this.deleteClass(removeLists.stream().map(TeachingClassInput::getTeachingClassId).collect(Collectors.toList()));
        List<TeachingClass> teachingClassListReturn = new ArrayList<>(this.addBatchTeachingClassV2(schoolId,term,addLists, false));
        updateLists.forEach(a -> {
            TeachingClass teachingClass = this.updateTeachingClassV2(schoolId,term,a);
            teachingClassListReturn.add(teachingClass);
        });
        this.updateBatchTeachingClass(updateBaseLists);
        teachingClassListReturn.addAll(BeanUtil.copyToList(updateBaseLists, TeachingClass.class));

        //更新教学班设置的授课类型对应的教室
        updateLists.addAll(updateBaseLists);
        courseService.updateTeachingClassWeek(updateLists);

        return teachingClassListReturn;
    }

    @Override
    public List<TeachingClassTeacher> updateTeacher(Long teachingClassId, List<Long> teacherIds) {
        //教学班对应教师
        List<TeachingClassTeacher> teachingClassTeacherList = new ArrayList<>();
        teachingClassTeacherMapper.delete(new LambdaQueryWrapper<TeachingClassTeacher>().eq(TeachingClassTeacher::getTeachingClassId, teachingClassId));
        if (CollUtil.isNotEmpty(teacherIds)) {
            teacherIds.forEach(teacherId -> teachingClassTeacherList.add(new TeachingClassTeacher()
                    .setTeachingClassId(teachingClassId)
                    .setTeacherId(teacherId)
                    .setTeacherType(0)));
        }
        teachingClassTeacherMapper.addBatch(teachingClassTeacherList);
        return teachingClassTeacherList;
    }

    @Override
    public List<TeachingClassStudent> updateStudent(Long teachingClassId, List<Long> studentIds) {
        //教学班对应学生
        List<TeachingClassStudent> teachingClassStudentList = new ArrayList<>();
        teachingClassStudentMapper.delete(new LambdaQueryWrapper<TeachingClassStudent>().eq(TeachingClassStudent::getTeachingClassId, teachingClassId));
        if (CollUtil.isNotEmpty(studentIds)) {
            studentIds.forEach(studentId -> teachingClassStudentList.add(new TeachingClassStudent()
                    .setTeachingClassId(teachingClassId)
                    .setStudentId(studentId)
                    .setFlag(1)));
        }
        //批量插入教学班学生，大数据批量插入
        Consumer<List<TeachingClassStudent>> studentConsumer = o -> teachingClassStudentMapper.addBatch(o);
        BatchInsert.batchSplitInsert(teachingClassStudentList, studentConsumer);
        return teachingClassStudentList;
    }

    @Override
    public Boolean updateBatchTeachingClass(List<TeachingClassInput> list) {
        List<TeachingClass> teachingClassList = BeanUtil.copyToList(list, TeachingClass.class);
        this.updateBatchById(teachingClassList);
        return true;
    }

    @Override
    public Boolean isExistTeachingClassName(String schoolId, String term, Long teachingClassId, String teachingClassName) {
        boolean exists = false;
        List<TaskInfo> taskInfos = taskInfoService.lambdaQuery().eq(TaskInfo::getSchoolId, schoolId).eq(TaskInfo::getTerm, term).list();
        //一个学期没几个任务  不用in查询，遍历查询
        for (TaskInfo taskInfo : taskInfos) {
            exists = this.lambdaQuery().eq(TeachingClass::getTaskId, taskInfo.getTaskId())
                    .eq(TeachingClass::getTeachingClassName, teachingClassName)
                    .ne(TeachingClass::getTeachingClassType, 3)
                    .ne(ObjUtil.isNotNull(teachingClassId), TeachingClass::getTeachingClassId, teachingClassId).exists();
            if (exists) {
                break;
            }
        }
        return exists;
    }

    @Override
    public Boolean combinedClass(List<Long> teachingClassIds) {
        if (CollUtil.isEmpty(teachingClassIds) || teachingClassIds.size() < 2) {
            return false;
        }
        //将其他教学班合到该教学班
        Long teachingClassId = teachingClassIds.get(0);
        teachingClassIds.remove(0);
        //合并教师
        teachingClassTeacherMapper.update(new TeachingClassTeacher().setTeachingClassId(teachingClassId), new LambdaQueryWrapper<TeachingClassTeacher>().in(TeachingClassTeacher::getTeachingClassId, teachingClassIds));
        //合并学生
        teachingClassStudentMapper.update(new TeachingClassStudent().setTeachingClassId(teachingClassId), new LambdaQueryWrapper<TeachingClassStudent>().in(TeachingClassStudent::getTeachingClassId, teachingClassIds));
        //删除教学班参数
        this.deleteClass(teachingClassIds);
        return true;
    }


    @Override
    public List<TeachingClass> getByCourseIdAndStudyNature(Integer flag, Long courseId, Integer studyNature, Integer teachingClassType) {
        //获取教学班
        List<TeachingClass> list = teachingClassMapper.getTeachingClassByCourseId(flag, courseId, studyNature, teachingClassType);
        //填充教师信息
        List<Long> teachingClassIds = list.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
        Map<Long, List<Teacher>> collect = teacherService.getTeacherByTeachingClassIds(teachingClassIds).stream()
                .collect(Collectors.groupingBy(Teacher::getTeachingClassId));
        list.forEach(a -> a.setTeachers(collect.get(a.getTeachingClassId())));
        //填充周次数据
        if (CollUtil.isNotEmpty(teachingClassIds)) {
            List<TeachingClassWeek> teachingClassWeekList = teachingClassWeekService.list(new LambdaQueryWrapper<TeachingClassWeek>().in(TeachingClassWeek::getTeachingClassId, teachingClassIds));
            Map<Long, List<TeachingClassWeek>> weekMap = teachingClassWeekList.stream().collect(Collectors.groupingBy(TeachingClassWeek::getTeachingClassId));
            list.forEach(a -> a.setCourseWeeks(weekMap.get(a.getTeachingClassId())));
        }
        return list;
    }

    @Override
    public Long getTeachingClassNumByCourseId(String schoolId, String term, Integer flag, Long courseId) {
        List<Integer> taskIds = taskInfoService.lambdaQuery().eq(TaskInfo::getSchoolId, schoolId).eq(TaskInfo::getTerm, term).list()
                .stream().map(TaskInfo::getTaskId).collect(Collectors.toList());
        List<TeachingClass> teachingClassList = new ArrayList<>();
        if (flag == 1) {
            //获取本学期 该课程的课程id
            Course course = courseService.getById(courseId);
            List<Long> courseIds = courseService.lambdaQuery().eq(Course::getBaseCourseId, course.getBaseCourseId())
                    .in(Course::getTaskId, taskIds).list().stream()
                    .map(Course::getCourseId).collect(Collectors.toList());
            teachingClassList = this.lambdaQuery().in(TeachingClass::getCourseId, courseIds).eq(TeachingClass::getFlag, 1)
                    .ne(TeachingClass::getTeachingClassType, 3).select(TeachingClass::getTeachingClassName).list();
        } else {
            Segment segment = segmentService.getById(courseId);
            List<Long> segmentIds = segmentService.lambdaQuery().eq(Segment::getBaseSegmentId, segment.getBaseSegmentId())
                    .in(Segment::getTaskId, taskIds).list().stream()
                    .map(Segment::getSegmentId).collect(Collectors.toList());
            teachingClassList = this.lambdaQuery().in(TeachingClass::getCourseId, segmentIds).eq(TeachingClass::getFlag, 2)
                    .select(TeachingClass::getTeachingClassName).list();
        }
        return findMaxNumber(teachingClassList.stream().map(TeachingClass::getTeachingClassName).collect(Collectors.toList()));
    }

    private Long findMaxNumber(List<String> teachingClassNames) {
        Pattern r = Pattern.compile("(\\d+)(班)");
        long max = 0L;
        for (String teachingClassName : teachingClassNames) {
            Matcher matcher = r.matcher(teachingClassName);
            if (matcher.find()) {
                long num = Long.parseLong(matcher.group(1));
                if (num > max) {
                    max = num;
                }
            }
        }
        return max;
    }


    @Override
    public PageInfo<TeachingClassCourseDto> getTeachingClassDtoByConditions(IPage page, Integer taskId, Integer handleState, Integer selectState, String courseTypeId, Integer studyNature, Integer courseNature, Integer majorProp, String collegeId, String keyWord, Integer teachingClassType, Integer minClassNum) {
        IPage<TeachingClassCourseDto> teachingClassByConditions = teachingClassMapper.getTeachingClassByConditions(page, taskId, handleState, selectState, courseTypeId, studyNature, courseNature, majorProp, collegeId, keyWord, teachingClassType, minClassNum);
        //填充其他数据
        //获取最低开班人数
        List<TeachingClassCourseDto> records = teachingClassByConditions.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            List<Long> teachingClassIds = records.stream().map(a -> a.getTeachingClassId()).collect(Collectors.toList());
            Map<Long, List<Teacher>> teachingClassToTeacher = teacherService.getTeacherByTeachingClassIds(teachingClassIds).stream()
                    .collect(Collectors.groupingBy(Teacher::getTeachingClassId));
            //填充周次数据
            List<TeachingClassWeek> teachingClassWeekList = teachingClassWeekService.list(new LambdaQueryWrapper<TeachingClassWeek>().in(TeachingClassWeek::getTeachingClassId, teachingClassIds));
            Map<Long, List<TeachingClassWeek>> weekMap = teachingClassWeekList.stream().collect(Collectors.groupingBy(TeachingClassWeek::getTeachingClassId));
            records.forEach(a -> {
                a.setTeachers(teachingClassToTeacher.get(a.getTeachingClassId()));
                //选课状态
                a.setSelectState(a.getStudentNumber() < a.getClassNum() ? 1 : 2);
                //周次
                a.setCourseWeeks(weekMap.get(a.getTeachingClassId()));
            });
        }
        teachingClassByConditions.setRecords(records);
        return PagingUtil.formatPageResult(teachingClassByConditions);
    }

    @Override
    public PageInfo<TeachingClassCourseDto> getSelectionTeachingClass(IPage page, Integer taskId, Integer handleState, Integer selectState, String courseTypeId, Integer studyNature, Integer courseNature, Integer majorProp, String collegeId, String keyWord, Integer minClassNum) {
        IPage<TeachingClassCourseDto> teachingClassByConditions = teachingClassMapper.getSelectionTeachingClass(page, taskId, handleState, selectState, courseTypeId, studyNature, courseNature, majorProp, collegeId, keyWord, minClassNum);
        //填充其他数据
        List<TeachingClassCourseDto> records = teachingClassByConditions.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            List<Long> teachingClassIds = records.stream().map(a -> a.getTeachingClassId()).collect(Collectors.toList());
            Map<Long, List<Teacher>> teachingClassToTeacher = teacherService.getTeacherByTeachingClassIds(teachingClassIds).stream()
                    .collect(Collectors.groupingBy(Teacher::getTeachingClassId));
            records.forEach(a -> {
                a.setTeachers(teachingClassToTeacher.get(a.getTeachingClassId()));
                //选课状态
                a.setSelectState(a.getStudentNumber() < minClassNum ? 1 : 2);
            });
        }
        teachingClassByConditions.setRecords(records);
        return PagingUtil.formatPageResult(teachingClassByConditions);
    }

    @Override
    public PageInfo<RuleTeachingClassVo> getSimpleTeachingClass(Integer taskId, IPage page, String courseTypeId, Integer courseNature, Integer majorProp, String collegeId, String keyWord, Integer state) {
        IPage<RuleTeachingClassVo> teachingClass = teachingClassMapper.getSimpleTeachingClass(page, taskId, courseTypeId, courseNature, majorProp, collegeId, keyWord, state);
        List<RuleTeachingClassVo> records = teachingClass.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            List<Long> teachingClassIds = records.stream().map(RuleTeachingClassVo::getTeachingClassId).collect(Collectors.toList());
            Map<Long, List<Teacher>> teachingClassToTeacher = teacherService.getTeacherByTeachingClassIds(teachingClassIds).stream()
                    .collect(Collectors.groupingBy(Teacher::getTeachingClassId));
            records.forEach(a -> a.setTeachers(teachingClassToTeacher.get(a.getTeachingClassId())));
        }
        teachingClass.setRecords(records);
        return PagingUtil.formatPageResult(teachingClass);
    }


    @Override
    public PageInfo<TeachingClassCourseDto> getTeachingClass(IPage page, Integer taskId, String courseTypeId, Integer studyNature, Integer courseNature, Integer majorProp, String collegeId, List<Long> classIds, String keyWord, Long roomId) {
        IPage<TeachingClassCourseDto> teachingClassByConditions = new Page<>();
        if (CollUtil.isNotEmpty(classIds)) {
            teachingClassByConditions = teachingClassMapper.getTeachingClass(page, taskId, courseTypeId, studyNature, courseNature, majorProp, collegeId, classIds, keyWord);
        } else {
            //null表示查询所有  非空但是size为0表示查询不到
            if (ObjUtil.isNotNull(classIds)) {
                return PagingUtil.formatPageResult(teachingClassByConditions);
            }
            teachingClassByConditions = teachingClassMapper.getTeachingClass(page, taskId, courseTypeId, studyNature, courseNature, majorProp, collegeId, null, keyWord);
        }
        List<TeachingClassCourseDto> records = teachingClassByConditions.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            List<Long> teachingClassIds = records.stream().map(TeachingClassCourseDto::getTeachingClassId).collect(Collectors.toList());
            Map<Long, List<Teacher>> teachingClassToTeacher = teacherService.getTeacherByTeachingClassIds(teachingClassIds).stream()
                    .collect(Collectors.groupingBy(Teacher::getTeachingClassId));
            //填充周次数据
            List<TeachingClassWeek> teachingClassWeekList = teachingClassWeekService.list(new LambdaQueryWrapper<TeachingClassWeek>().in(TeachingClassWeek::getTeachingClassId, teachingClassIds));
            Map<Long, List<TeachingClassWeek>> weekMap = teachingClassWeekList.stream().collect(Collectors.groupingBy(TeachingClassWeek::getTeachingClassId));
            //课表信息
            List<ScheduleDto> scheduleDtoList = scheduleMapper.getScheduleByTeachingClassIdsAndRoomId(null, teachingClassIds, roomId);
            Map<Long, List<ScheduleDto>> scheduleMap = scheduleDtoList.stream().collect(Collectors.groupingBy(ScheduleDto::getTeachingClassId));
            records.forEach(a -> {
                a.setTeachers(teachingClassToTeacher.getOrDefault(a.getTeachingClassId(), ListUtil.empty()));
                //周次
                a.setCourseWeeks(weekMap.getOrDefault(a.getTeachingClassId(), ListUtil.empty()));
                //课表
                a.setSchedules(scheduleMap.getOrDefault(a.getTeachingClassId(), ListUtil.empty()));
            });
        }
        teachingClassByConditions.setRecords(records);
        return PagingUtil.formatPageResult(teachingClassByConditions);
    }

    @Override
    public List<TeachingClassToClassDto> getTeachingClassByClass(Integer taskId, List<String> classIds) {
        List<TeachingClassToClassDto> teachingClassByConditions = new ArrayList<>();
        if (CollUtil.isEmpty(classIds)) {
            return teachingClassByConditions;
        }

        teachingClassByConditions = teachingClassMapper.getTeachingClassByClassId(taskId, classIds);
        if (CollUtil.isNotEmpty(teachingClassByConditions)) {
            List<Long> teachingClassIds = teachingClassByConditions.stream().map(TeachingClassToClassDto::getTeachingClassId).collect(Collectors.toList());
            Map<Long, List<Teacher>> teachingClassToTeacher = teacherService.getTeacherByTeachingClassIds(teachingClassIds).stream()
                    .collect(Collectors.groupingBy(Teacher::getTeachingClassId));
            //填充周次数据
            List<TeachingClassWeek> teachingClassWeekList = teachingClassWeekService.list(new LambdaQueryWrapper<TeachingClassWeek>().in(TeachingClassWeek::getTeachingClassId, teachingClassIds));
            Map<Long, List<TeachingClassWeek>> weekMap = teachingClassWeekList.stream().collect(Collectors.groupingBy(TeachingClassWeek::getTeachingClassId));
            //课表信息
            List<ScheduleDto> scheduleDtoList = scheduleMapper.getScheduleByTeachingClassIdsAndRoomId(null, teachingClassIds, null);
            Map<Long, List<ScheduleDto>> scheduleMap = scheduleDtoList.stream().collect(Collectors.groupingBy(ScheduleDto::getTeachingClassId));
            teachingClassByConditions.forEach(a -> {
                a.setTeachers(teachingClassToTeacher.getOrDefault(a.getTeachingClassId(), ListUtil.empty()));
                //周次
                a.setCourseWeeks(weekMap.getOrDefault(a.getTeachingClassId(), ListUtil.empty()));
                //课表
                a.setSchedules(scheduleMap.getOrDefault(a.getTeachingClassId(), ListUtil.empty()));
            });
        }
        return teachingClassByConditions;
    }

    @Override
    public PageInfo<TeachingClassSegmentDto> getSegmentTeachingClass(IPage page, Integer taskId, String courseTypeId, Integer studyNature, String collegeId, List<Long> classIds, String keyWord) {
        IPage<TeachingClassSegmentDto> teachingClassByConditions = new Page<>();
        if (CollUtil.isNotEmpty(classIds)) {
            teachingClassByConditions = teachingClassMapper.getSegmentTeachingClass(page, taskId, courseTypeId, studyNature, collegeId, classIds, keyWord);
        } else {
            //null表示查询所有  非空但是size为0表示查询不到
            if (ObjUtil.isNotNull(classIds)) {
                return PagingUtil.formatPageResult(teachingClassByConditions);
            }
            teachingClassByConditions = teachingClassMapper.getSegmentTeachingClass(page, taskId, courseTypeId, studyNature, collegeId, null, keyWord);
        }
        List<TeachingClassSegmentDto> records = teachingClassByConditions.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            List<Long> teachingClassIds = records.stream().map(TeachingClassSegmentDto::getTeachingClassId).collect(Collectors.toList());
            Map<Long, List<Teacher>> teachingClassToTeacher = teacherService.getTeacherByTeachingClassIds(teachingClassIds).stream()
                    .collect(Collectors.groupingBy(Teacher::getTeachingClassId));
            //填充周次数据
            List<TeachingClassWeek> teachingClassWeekList = teachingClassWeekService.list(new LambdaQueryWrapper<TeachingClassWeek>().in(TeachingClassWeek::getTeachingClassId, teachingClassIds));
            Map<Long, List<TeachingClassWeek>> weekMap = teachingClassWeekList.stream().collect(Collectors.groupingBy(TeachingClassWeek::getTeachingClassId));
            records.forEach(a -> {
                a.setTeachers(teachingClassToTeacher.get(a.getTeachingClassId()));
                //周次
                a.setCourseWeeks(weekMap.get(a.getTeachingClassId()));
            });
        }
        teachingClassByConditions.setRecords(records);
        return PagingUtil.formatPageResult(teachingClassByConditions);
    }

    @Override
    public PageInfo<TeachingClassSegmentDto> getTeachingClassSegment(IPage page, Integer taskId, String segmentTypeId, Integer studyNature, String collegeId, String keyWord) {
        IPage<TeachingClassSegmentDto> teachingClassSegment = teachingClassMapper.getTeachingClassSegment(page, taskId, segmentTypeId, studyNature, collegeId, keyWord);
        List<TeachingClassSegmentDto> records = teachingClassSegment.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            List<Long> teachingClassIds = records.stream().map(a -> a.getTeachingClassId()).collect(Collectors.toList());
            //教师
            Map<Long, List<Teacher>> teachingClassToTeacher = teacherService.getTeacherByTeachingClassIds(teachingClassIds).stream()
                    .collect(Collectors.groupingBy(Teacher::getTeachingClassId));
            //填充周次数据
            List<TeachingClassWeek> teachingClassWeekList = teachingClassWeekService.list(new LambdaQueryWrapper<TeachingClassWeek>().in(TeachingClassWeek::getTeachingClassId, teachingClassIds));
            Map<Long, List<TeachingClassWeek>> weekMap = teachingClassWeekList.stream().collect(Collectors.groupingBy(TeachingClassWeek::getTeachingClassId));
            records.forEach(a -> {
                a.setTeachers(teachingClassToTeacher.get(a.getTeachingClassId()));
                //周次
                a.setCourseWeeks(weekMap.get(a.getTeachingClassId()));
            });
        }
        teachingClassSegment.setRecords(records);
        return PagingUtil.formatPageResult(teachingClassSegment);

    }

    @Override
    public void updateTeachingClassEnable(List<Long> teachingClassIds, Integer isEnable) {
        LambdaUpdateWrapper<TeachingClass> updateWrapper = new LambdaUpdateWrapper<TeachingClass>()
                .in(TeachingClass::getTeachingClassId, teachingClassIds)
                .set(TeachingClass::getIsEnable, isEnable);
        this.update(updateWrapper);
        //在线选课 取消开班 发送消息
        if (isEnable == 0) {
            // 发送消息
            Integer taskId = Integer.parseInt(request.getHeader("taskId"));
            String userId = request.getHeader("userId");
            String userName = request.getHeader("userName");
            String authorization = request.getHeader("Authorization");
            yunBasicService.sendSelectCourseCancelMsg(teachingClassIds, taskId, userId, userName, authorization);
        }

    }

    @Override
    public PublishStatisticsPre preStatistics(Integer taskId, Integer teachingClassType, Integer minClassNum) {
        PublishStatisticsPre publishStatisticsPre = new PublishStatisticsPre();
        List<TeachingClassCourseDto> list = teachingClassMapper.getSelectStatistic(taskId, teachingClassType);
        int releaseNumber = list.size();
        long notReachedNumber = 0;
        if (teachingClassType == 1) {
            notReachedNumber = list.stream().filter(a -> a.getStudentNumber() < minClassNum).count();
        } else {
            notReachedNumber = list.stream().filter(a -> a.getStudentNumber() < a.getClassNum()).count();
        }
        //统计学生数量并去重 or 不去重
        publishStatisticsPre.setReleaseNumber(releaseNumber)
                .setNotReachedNumber(notReachedNumber)
                .setStandardNumber(releaseNumber - notReachedNumber)
                .setStudentNumber(teachingClassMapper.getSelectStudent(taskId, teachingClassType));
        return publishStatisticsPre;
    }

    @Override
    public PublishDeselectStatistic getDeselectStatistic(Integer taskId) {
        PublishDeselectStatistic publishDeselectStatistic = new PublishDeselectStatistic();
        List<TeachingClassCourseDto> list = teachingClassMapper.getDeselectStatistic(taskId);
        int totalNumber = list.size();
        long deselectNumber = list.stream().filter(a -> a.getStudentNumber() > 0).count();
        //统计学生数量并去重 or 不去重
        int studentNumber = list.stream().mapToInt(TeachingClassCourseDto::getStudentNumber).sum();
        publishDeselectStatistic.setTotalNumber(totalNumber)
                .setDeselectNumber(deselectNumber)
                .setStudentNumber(studentNumber);
        return publishDeselectStatistic;
    }


    @Override
    public List<Teacher> getTeacherByCourseId(Long courseId, Integer teachingClassType) {
        //获取教学班
        List<TeachingClass> list = this.list(new LambdaQueryWrapper<TeachingClass>().eq(TeachingClass::getCourseId, courseId)
                .eq(TeachingClass::getTeachingClassType, teachingClassType)
                .ne(TeachingClass::getFlag, 0));
        //填充教师信息
        List<Long> teachingClassIds = list.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
        List<Teacher> teacherList = teacherService.getTeacherByTeachingClassIds(teachingClassIds).stream().distinct().collect(Collectors.toList());
        return teacherList;
    }

    @Override
    public List<Teacher> getTeacherByTeachingId(Long teachingClassId) {
        List<Teacher> teacherList = teacherService.getTeacherByTeachingClassIds(Arrays.asList(teachingClassId)).stream().distinct().collect(Collectors.toList());
        return teacherList;
    }

    @Override
    public SubTeachingClass getSubTeachingClass(Integer taskId, String classId) {
        SubTeachingClass sub = new SubTeachingClass();
        //教学班参数 任课教师 课程 roomName
        List<TeachingClassSubVoNew> subTeachingClass = teachingClassMapper.getSubTeachingClass(taskId, classId);
        if (CollUtil.isNotEmpty(subTeachingClass)) {
            List<Long> teachingClassIds = subTeachingClass.stream().map(TeachingClassSubVoNew::getTeachingClassId).collect(Collectors.toList());
            //教师信息
            Map<Long, List<Teacher>> teachingClassToTeacher = teacherService.getTeacherByTeachingClassIds(teachingClassIds).stream()
                    .collect(Collectors.groupingBy(Teacher::getTeachingClassId));
            List<Long> roomIds = subTeachingClass.stream().map(TeachingClassSubVoNew::getRoomId)
                    .filter(Objects::nonNull)
                    .flatMap(roomId -> Arrays.stream(roomId.split(",")))
                    .filter(StrUtil::isNotBlank)
                    .map(Long::parseLong)
                    .distinct().collect(Collectors.toList());
            //教室信息
            Map<Long, String> roomMap = new HashMap<>();
            if (CollUtil.isNotEmpty(roomIds)) {
                roomMap = roomService.lambdaQuery().in(Room::getRoomId, roomIds).list()
                        .stream().collect(Collectors.toMap(Room::getRoomId, Room::getRoomName));
            }
            //填充周次数据
            List<TeachingClassWeek> teachingClassWeekList = teachingClassWeekService.list(new LambdaQueryWrapper<TeachingClassWeek>().in(TeachingClassWeek::getTeachingClassId, teachingClassIds));
            Map<Long, List<TeachingClassWeek>> weekMap = teachingClassWeekList.stream().collect(Collectors.groupingBy(TeachingClassWeek::getTeachingClassId));
            Map<Long, String> finalRoomMap = roomMap;
            subTeachingClass.forEach(teachingClass -> {
                teachingClass.setTeachers(teachingClassToTeacher.get(teachingClass.getTeachingClassId()));
                teachingClass.setTeachingClassWeeks(weekMap.get(teachingClass.getTeachingClassId()));
                //教室名称
                String roomNames = "";
                if (StrUtil.isNotBlank(teachingClass.getRoomId())) {
                    for (String s : teachingClass.getRoomId().split(",")) {
                        roomNames = roomNames + finalRoomMap.get(Long.parseLong(s)) + ",";
                    }
                    if (roomNames.endsWith(",")) {
                        roomNames = roomNames.substring(0, roomNames.length() - 1); // 移除最后一个逗号
                    }
                }
                teachingClass.setRoomName(roomNames);
            });

        }
        //分组整理课程相关信息
        List<SubCourseVo> subCourseVoList = new ArrayList<>();
        for (TeachingClassSubVoNew value : subTeachingClass.stream().collect(Collectors.toMap(teachingClassSubVoNew -> teachingClassSubVoNew.getCourseId() + "-" + teachingClassSubVoNew.getRoomId(), Function.identity(), (key1, key2) -> key2)).values()) {
            subCourseVoList.add(new SubCourseVo().setCourseId(value.getCourseId())
                    .setCollegeId(value.getCollegeId())
                    .setRoomId(value.getRoomId())
                    .setStudyNature(value.getStudyNature())
                    .setCourseName(value.getCourseName())
                    .setRoomName(value.getRoomName())
                    .setTeachingClassWeeks(value.getTeachingClassWeeks())
                    .setTeachers(value.getTeachers()));
        }
        List<Student> students = studentService.lambdaQuery().eq(Student::getTaskId, taskId).eq(Student::getClassId, classId).list();
        if (CollUtil.isNotEmpty(students)) {
            //获取学生信息 odd奇数  even偶数
            List<Long> oddStudentId = new ArrayList<>();
            List<Long> evenStudentId = new ArrayList<>();
            for (Student student : students) {
                String baseStudentId = student.getBaseStudentId();
                if (baseStudentId != null && baseStudentId.length() > 0) {
                    char lastChar = baseStudentId.charAt(baseStudentId.length() - 1);
                    // 根据isSingle判断过滤单数 或复数
                    if (((int) lastChar % 2 != 0)) {
                        oddStudentId.add(student.getStudentId());
                    } else {
                        evenStudentId.add(student.getStudentId());
                    }
                }
            }
            //获取校区信息
            Student student = students.get(0);
            Major major = majorService.lambdaQuery().eq(Major::getTaskId, taskId)
                    .eq(Major::getBaseMajorId, student.getMajorId())
                    .eq(Major::getCollegeId, student.getCollegeId())
                    .eq(Major::getGradeId, student.getGradeId()).one();
            sub.setOddStudentId(oddStudentId)
                    .setEvenStudentId(evenStudentId)
                    .setCampusId(major.getCampusId())
                    .setCampusName(major.getCampusName());

        }

        sub.setTeachingClassSubVoNews(subTeachingClass);
        sub.setSubCourseVos(subCourseVoList);
        return sub;
    }

    @Override
    public List<TeachingClass> getByUniqueShiftSign(String uniqueShiftSign) {
        //获取教学班
        List<TeachingClass> list = teachingClassMapper.getTeachingClassByShiftsign(uniqueShiftSign);
        //填充教师信息
        List<Long> teachingClassIds = list.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
        Map<Long, List<Teacher>> collect = teacherService.getTeacherByTeachingClassIds(teachingClassIds).stream()
                .collect(Collectors.groupingBy(Teacher::getTeachingClassId));
        list.forEach(a -> a.setTeachers(collect.get(a.getTeachingClassId())));
        //填充周次数据
        if (CollUtil.isNotEmpty(teachingClassIds)) {
            List<TeachingClassWeek> teachingClassWeekList = teachingClassWeekService.list(new LambdaQueryWrapper<TeachingClassWeek>().in(TeachingClassWeek::getTeachingClassId, teachingClassIds));
            Map<Long, List<TeachingClassWeek>> weekMap = teachingClassWeekList.stream().collect(Collectors.groupingBy(TeachingClassWeek::getTeachingClassId));
            list.forEach(a -> a.setCourseWeeks(weekMap.get(a.getTeachingClassId())));
        }
        return list;
    }

    @Override
    public String allTeachingClassToExcel(Integer taskId, String importMode) {
        String modelPath = GlobalConstant.MODEL_EXCEL_PATH + "【模板】教学班信息 (大学排课).xls";
        TaskInfo taskInfo = taskInfoService.getById(taskId);
        String storePath = "/" + taskInfo.getTaskName() + "/syncTeachingClass.xlsx";
        String targetPath = GlobalConstant.OUTPUT_EXCEL_PATH + storePath;

        FileUtil.copy(modelPath, targetPath, true);
        ExcelWriter writer = ExcelUtil.getWriter(targetPath);
        writer.setSheet(0);
        writer.passCurrentRow();
        writer.passCurrentRow();
        String httpPath = "/static/OutputExcel" + storePath;

        //后修改为COVER全部 INCREMENT在线选课教学班
        List<SyncTeachingClassDto> courseTeachingClassList = new ArrayList<>();
        if (importMode.equals(CommonConstants.COVER)) {
            //课程教学班
            courseTeachingClassList = teachingClassMapper.syncCourseTeachingClassDto(taskId, 4);
            //添加环节教学班
            courseTeachingClassList.addAll(teachingClassMapper.syncSegmentTeachingClassDto(taskId));
        } else {
            courseTeachingClassList = teachingClassMapper.syncCourseTeachingClassDto(taskId, 1);
        }
        if (CollUtil.isEmpty(courseTeachingClassList)) {
            writer.close();
            return httpPath;
        }
        List<Long> teachingClassIds = courseTeachingClassList.stream().map(SyncTeachingClassDto::getTeachingClassId).collect(Collectors.toList());
        //获取行政班 及对应年级
        Map<String, ClassDto> classMap = studentMapper.getClassDto(taskId, null, null, null)
                .stream().collect(Collectors.toMap(ClassDto::getClassId, a -> a));
        //教学班学生
        Map<Long, List<ExcelStudent>> studentMap = studentMapper.getExcelStudent(teachingClassIds)
                .stream().collect(Collectors.groupingBy(ExcelStudent::getTeachingClassId));
        //获取教师信息
        Map<Long, List<Teacher>> teachingClassToTeacher = teacherService.getTeacherByTeachingClassIds(teachingClassIds).stream()
                .collect(Collectors.groupingBy(Teacher::getTeachingClassId));
        //年级对应年级统一标识
        Map<String, String> globalGradeMap = yunBasicService.getGrade(taskInfo.getSchoolId())
                .stream().collect(Collectors.toMap(BaseGrade::getGradeID, BaseGrade::getGlobalGrade));

        List<List<String>> rows = new ArrayList<>();
        for (SyncTeachingClassDto teachingClass : courseTeachingClassList) {
            String courseName = "";
            String teachingClassName = "";
            //暂且只有一个老师
            String teacherId = "";
            //上课对象字符串 C|2021级英语2班,2021级英语3班;S|stu036,stu037. 去掉已存行政班的学生
            String students = "";
            String globalGrade = globalGradeMap.size() > 0 ? new ArrayList<>(globalGradeMap.values()).get(0) : "U1";
            globalGrade = StrUtil.isBlank(teachingClass.getToClass()) ? globalGrade : globalGradeMap.getOrDefault(teachingClass.getToClass(), globalGrade);
            //teachingClass.getUniqueShiftSign() 不为null表示是拆班数据。学生传的是学生字符串
            if (StrUtil.isNotBlank(teachingClass.getUniqueShiftSign())) {
                courseName = teachingClass.getCourseName();
                teachingClassName = teachingClass.getTeachingClassName();
                if (teachingClassToTeacher.containsKey(teachingClass.getTeachingClassId())) {
                    teacherId = teachingClassToTeacher.get(teachingClass.getTeachingClassId()).get(0).getBaseTeacherId();
                }
                //学生字符串
                students = studentMap.getOrDefault(teachingClass.getTeachingClassId(), new ArrayList<>()).stream()
                        .map(ExcelStudent::getBaseStudentId).collect(Collectors.joining(","));
                if (StrUtil.isNotBlank(students)) {
                    students = "S|" + students;
                }
                List<String> row = CollUtil.newArrayList(courseName, teachingClassName, teacherId, "覆盖", students, globalGrade);
                rows.add(row);
            } else {
                courseName = teachingClass.getCourseName();
                teachingClassName = teachingClass.getTeachingClassName();
                if (teachingClassToTeacher.containsKey(teachingClass.getTeachingClassId())) {
                    teacherId = teachingClassToTeacher.get(teachingClass.getTeachingClassId()).get(0).getBaseTeacherId();
                }
                //学生字符串
                students = studentMap.getOrDefault(teachingClass.getTeachingClassId(), new ArrayList<>()).stream()
                        .filter(student -> !teachingClass.getToClass().contains(student.getClassId()))
                        .map(ExcelStudent::getBaseStudentId).collect(Collectors.joining(","));
                if (StrUtil.isNotBlank(students)) {
                    students = "S|" + students;
                }
                if (StrUtil.isNotBlank(teachingClass.getToClass()) && StrUtil.isNotBlank(students)) {
                    students = students + ";";
                }
                if (StrUtil.isNotBlank(teachingClass.getToClass())) {
                    //行政班id转化为行政班名称
                    String[] classIds = teachingClass.getToClass().split(",");
                    String className = Arrays.stream(classIds).map(a -> classMap.get(a).getClassName()).collect(Collectors.joining(","));
                    students = students + "C|" + className;
                }
                List<String> row = CollUtil.newArrayList(courseName, teachingClassName, teacherId, "覆盖", students, globalGrade);
                rows.add(row);
            }
        }
        writer.write(rows, false);
        writer.close();
        return httpPath;
    }

    @Override
    public String teachTaskToExcel(Integer taskId, String collegeId, String collegeName, String courseTypeId, String courseType, Integer courseNature, Integer studyNature) {
        String modelPath = GlobalConstant.MODEL_EXCEL_PATH + "03 教学任务模板.xlsx";

        TaskInfo taskInfo = taskInfoService.getById(taskId);
        String storePath = "/" + taskInfo.getTaskName() + "/教学任务-" + LocalDate.now() + ".xlsx";
        String targetPath = GlobalConstant.OUTPUT_EXCEL_PATH + storePath;
        FileUtil.copy(modelPath, targetPath, true);
        ExcelWriter writer = ExcelUtil.getWriter(targetPath);

        Page<TeachingClassCourseDto> page = new Page<>(1, -1);
        PageInfo<TeachingClassCourseDto> teachingClassPage = this.getTeachingClassDtoByConditions(page, taskId, null, null, courseTypeId, studyNature, courseNature, null, collegeId, null, 4, null);
        List<TeachingClassCourseDto> resultList = teachingClassPage.getList();
        writer.write(Arrays.asList(taskInfo.getSchoolName() + "教学任务 \n " + taskInfo.getTermName()));
        StringBuilder stringBuilder = StrUtil.builder().append("开课单位：").append(StrUtil.isBlank(collegeId) ? "全部学院  " : collegeName + "  ")
                .append("课程类别：").append(StrUtil.isBlank(courseTypeId) ? "全部  " : courseType + "  ")
                .append("课程性质：").append(ObjUtil.isNull(courseNature) ? "全部  " : (courseNature == 1 ? "必修  " : "选修  "))
                .append("修读性质：").append(ObjUtil.isNull(studyNature) ? "全部  " : (studyNature == 1 ? "主修  " : "辅修  "))
                .append("共：").append(resultList.size() + "个教学班  ")
                .append("导出时间：").append(DateUtil.now());
        writer.write(Arrays.asList(stringBuilder.toString()));
        writer.passCurrentRow();
        List<List<String>> rows = new ArrayList<>();
        List<String> row;
        Map<Integer, String> roomTypeMap = roomTypeService.lambdaQuery().eq(RoomType::getSchoolId, taskInfo.getSchoolId())
                .eq(RoomType::getTerm, taskInfo.getTerm()).list()
                .stream().collect(Collectors.toMap(RoomType::getId, RoomType::getTypeName));
        for (TeachingClassCourseDto item : resultList) {
            //任课教师名称
            String teacherName = ExcelFormatUtil.getTeacherName(item.getTeachers());
            //周学时
            String weekDistribution = ExcelFormatUtil.getWeekHourString(item.getCourseWeeks(),roomTypeMap);
            //周次
            String weeks = ExcelFormatUtil.getWeekString(item.getCourseWeeks());
            row = Arrays.asList(item.getCourseCode(), item.getCourseName(), item.getCollegeName(), item.getCourseType(),
                    item.getCourseNature().equals(1) ? "必修" : "选修", item.getStudyNature().equals(1) ? "主修" : "辅修",
                    item.getCredit().toString(), item.getTotalHour().toString(), item.getTeachingClassName(), teacherName, item.getStudentNumber().toString(),
                    weekDistribution, weeks);
            rows.add(row);
        }
        writer.write(rows, false);
        ExcelFormatUtil.setFont(writer);
        writer.close();
        return GlobalConstant.ACCESS_PATH + "/static/OutputExcel" + storePath;
    }

    @Override
    public String segmentToExcel(Integer taskId, String collegeId, String collegeName, String segmentTypeId, String segmentType, Integer studyNature) {
        TaskInfo taskInfo = taskInfoService.getById(taskId);
        String storePath = "/" + taskInfo.getTaskName() + "/环节教学任务-" + LocalDate.now() + ".xlsx";
        String targetPath = GlobalConstant.OUTPUT_EXCEL_PATH + storePath;

        FileUtil.del(targetPath);
        ExcelWriter writer = ExcelUtil.getWriter(targetPath);


        Page<TeachingClassSegmentDto> page = new Page<>(1, -1);
        PageInfo<TeachingClassSegmentDto> segmentClassPage = this.getTeachingClassSegment(page, taskId, segmentTypeId, studyNature, collegeId, null);
        List<TeachingClassSegmentDto> resultList = segmentClassPage.getList();
        writer.merge(8, taskInfo.getSchoolName() + "教学任务 \n " + taskInfo.getTermName());

        StringBuilder stringBuilder = StrUtil.builder().append("开课单位：").append(StrUtil.isBlank(collegeId) ? "全部学院  " : collegeName + "  ")
                .append("课程类别：").append(StrUtil.isBlank(segmentTypeId) ? "全部  " : segmentType + "  ")
                .append("修读性质：").append(ObjUtil.isNull(studyNature) ? "全部  " : (studyNature == 1 ? "主修  " : "辅修  "))
                .append("共：").append(resultList.size() + "个教学班  ")
                .append("导出时间：").append(DateUtil.now());
        writer.merge(8, stringBuilder);
        List<List<String>> rows = new ArrayList<>();
        rows.add(Arrays.asList("代码", "名称", "开课单位", "环节类型", "修读性质", "教学班名称", "任课教师", "班级人数", "周次(小周)"));
        List<String> row;
        for (TeachingClassSegmentDto item : resultList) {
            //任课教师名称
            String teacherName = ExcelFormatUtil.getTeacherName(item.getTeachers());
            //周次
            String weeks = "";
            if (CollUtil.isNotEmpty(item.getCourseWeeks())) {
                String week = item.getCourseWeeks().get(0).getWeek();
                weeks = WeekUtil.binaryToString(week);
            }
            row = Arrays.asList(item.getSegmentCode(), item.getSegmentName(), item.getCollegeName(), item.getSegmentType(),
                    item.getStudyNature().equals(1) ? "主修" : "辅修", item.getTeachingClassName(), teacherName, item.getStudentNumber().toString(), weeks);
            rows.add(row);
        }
        writer.write(rows, false);
        ExcelFormatUtil.setFont(writer);
        writer.close();
        return GlobalConstant.ACCESS_PATH + "/static/OutputExcel" + storePath;
    }

    @Override
    public String preSelectToExcel(Integer taskId, String collegeId, String collegeName, String courseTypeId, String courseType, Integer courseNature, Integer studyNature, Integer majorProp) {

        TaskInfo taskInfo = taskInfoService.getById(taskId);
        String storePath = "/" + taskInfo.getTaskName() + "/预选课程-" + LocalDate.now() + ".xlsx";
        String targetPath = GlobalConstant.OUTPUT_EXCEL_PATH + storePath;

        FileUtil.del(targetPath);
        ExcelWriter writer = ExcelUtil.getWriter(targetPath);

        Page<TeachingClassCourseDto> page = new Page<>(1, -1);
        PageInfo<TeachingClassCourseDto> teachingClassPage = this.getTeachingClassDtoByConditions(page, taskId, null, null, courseTypeId, studyNature, courseNature, majorProp, collegeId, null, 3, null);
        List<TeachingClassCourseDto> resultList = teachingClassPage.getList();
        String title = "{}预选课程  \n  {}";
        writer.merge(9, StrUtil.format(title, taskInfo.getSchoolName(), taskInfo.getTermName()), false);
        writer.setRowHeight(0, 40);
        String filterTem = "开课单位:{}  课程类别:{}  课程性质:{}  修读性质:{}  专业性质:{}   共:{}门   导出时间:{} ";
        String filter = StrUtil.format(filterTem, StrUtil.isBlank(collegeId) ? "全部学院  " : collegeName,
                StrUtil.isBlank(courseTypeId) ? "全部" : courseType,
                ObjUtil.isNull(courseNature) ? "全部" : (courseNature == 1 ? "必修" : "选修"),
                ObjUtil.isNull(studyNature) ? "全部" : (courseNature == 1 ? "主修" : "辅修"),
                ObjUtil.isNull(majorProp) ? "全部" : (majorProp == 1 ? "公共课" : "专业课"),
                resultList.size(), DateUtil.now());
        writer.merge(8, filter, false);
        List<List<String>> rows = new ArrayList<>();
        rows.add(Arrays.asList("代码", "名称", "开课单位", "课程类别", "课程性质", "修读性质", "教学班名称", "选课人数", "专业性质"));
        List<String> row;
        for (TeachingClassCourseDto item : resultList) {
            row = Arrays.asList(item.getCourseCode(), item.getCourseName(), item.getCollegeName(), item.getCourseType(),
                    item.getCourseNature().equals(1) ? "必修" : "选修", item.getStudyNature().equals(1) ? "主修" : "辅修",
                    item.getTeachingClassName(), item.getStudentNumber().toString(), item.getMajorProp().equals(1) ? "公共课" : "专业课");
            rows.add(row);
        }
        writer.write(rows, false);
        ExcelFormatUtil.setFont(writer);
        writer.close();
        return GlobalConstant.ACCESS_PATH + "/static/OutputExcel" + storePath;
    }

    @Override
    public String csSelectToExcel(Integer taskId, String collegeId, String collegeName, String courseTypeId, String courseType, Integer courseNature, Integer studyNature, Integer majorProp) {
        TaskInfo taskInfo = taskInfoService.getById(taskId);
        String storePath = "/" + taskInfo.getTaskName() + "/在线选课-" + LocalDate.now() + ".xlsx";
        String targetPath = GlobalConstant.OUTPUT_EXCEL_PATH + storePath;

        FileUtil.del(targetPath);
        ExcelWriter writer = ExcelUtil.getWriter(targetPath);

        Page<TeachingClassCourseDto> page = new Page<>(1, -1);
        PageInfo<TeachingClassCourseDto> teachingClassPage = this.getTeachingClassDtoByConditions(page, taskId, null, null, courseTypeId, studyNature, courseNature, majorProp, collegeId, null, 1, null);
        List<TeachingClassCourseDto> resultList = teachingClassPage.getList();
        String title = "{}在线选课  \n  {}";
        writer.merge(10, StrUtil.format(title, taskInfo.getSchoolName(), taskInfo.getTermName()), false);
        writer.setRowHeight(0, 40);
        String filterTem = "开课单位:{}  课程类别:{}  课程性质:{}  修读性质:{}  专业性质:{}  共:{}门   导出时间:{} ";
        String filter = StrUtil.format(filterTem, StrUtil.isBlank(collegeId) ? "全部学院  " : collegeName,
                StrUtil.isBlank(courseTypeId) ? "全部" : courseType,
                ObjUtil.isNull(courseNature) ? "全部" : (courseNature == 1 ? "必修" : "选修"),
                ObjUtil.isNull(studyNature) ? "全部" : (courseNature == 1 ? "主修" : "辅修"),
                ObjUtil.isNull(majorProp) ? "全部" : (majorProp == 1 ? "公共课" : "专业课"),
                resultList.size(), DateUtil.now());
        writer.merge(10, filter, false);
        List<List<String>> rows = new ArrayList<>();
        rows.add(Arrays.asList("代码", "名称", "开课单位", "课程类别", "课程性质", "修读性质", "专业性质", "教学班名称", "任课教师", "人数上限", "选课人数"));
        List<String> row;
        for (TeachingClassCourseDto item : resultList) {
            List<String> teacherNameList = new ArrayList<>();
            if (CollUtil.isNotEmpty(item.getTeachers())) {
                teacherNameList = item.getTeachers().stream().map(Teacher::getTeacherName).collect(Collectors.toList());
            }
            String teacherName = StrUtil.join(",", teacherNameList);
            row = Arrays.asList(item.getCourseCode(), item.getCourseName(), item.getCollegeName(), item.getCourseType(),
                    item.getCourseNature().equals(1) ? "必修" : "选修", item.getStudyNature().equals(1) ? "主修" : "辅修",
                    item.getMajorProp().equals(1) ? "公共课" : "专业课", item.getTeachingClassName(), teacherName,
                    item.getClassNum().toString(), item.getStudentNumber().toString());
            rows.add(row);
        }
        writer.write(rows, false);
        ExcelFormatUtil.setFont(writer);
        writer.close();
        return GlobalConstant.ACCESS_PATH + "/static/OutputExcel" + storePath;
    }

    @Override
    public List<TeachingClass> checkPublishTeachTask(Integer taskId){
        //查看未设置教室的单双号拆班数据
        return teachingClassMapper.getNotExistRoomTeachingClass(taskId);
    }


    @Override
    public boolean publishTeachTask(Integer taskId) {
        //修改教学班状态 未设置-》正常开班
        this.lambdaUpdate().set(TeachingClass::getIsEnable, 1)
                .eq(TeachingClass::getTaskId, taskId)
                .eq(TeachingClass::getIsEnable, 2).update();
        //将未设置教室单双号拆班教学班删除
        List<Long> teachingClassIds = teachingClassMapper.getNotExistRoomTeachingClass(taskId)
                .stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
        this.deleteClass(teachingClassIds);
        return true;
    }


    @Override
    public Boolean excelToTeachingClass(ImportTeachingClass importTeachingClass, MultipartFile file) {
        Integer taskId = importTeachingClass.getTaskId();
        TaskInfo taskInfo = taskInfoService.getById(taskId);

        Map<String, Long> teacherMap = new HashMap<>();
        Map<String, Long> studentMap = new HashMap<>();
        List<TeachingClassInput> teachingClassInputs = new ArrayList<>();

        InputStream inputStream = null;
        try {
            inputStream = file.getResource().getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream, 0);

            //增加表头别名
            reader.addHeaderAlias("教学班名称", "teachingClassName");
            reader.addHeaderAlias("任课教师工号", "teacherNos");
            reader.addHeaderAlias("上课对象", "studentNos");
            reader.addHeaderAlias("校区", "campusName");
            List<Map<String, Object>> addTeachingClass = reader.read(1, 2, reader.getColumnCount());
            //获取全部教师工号
            List<String> allTeacherNos = addTeachingClass.stream()
                    .map(o -> o.get("teacherNos").toString().split(","))
                    .flatMap(Arrays::stream)
                    .distinct()
                    .collect(Collectors.toCollection(ArrayList::new));

            //获取全部学生学号
            List<String> allStudentNos = addTeachingClass.stream()
                    .map(o -> o.get("studentNos").toString().split(","))
                    .flatMap(Arrays::stream)
                    .distinct()
                    .collect(Collectors.toList());
            //获取有的教师信息
            if (CollUtil.isNotEmpty(allTeacherNos)) {
                teacherMap = teacherService.lambdaQuery().in(Teacher::getBaseTeacherId, allTeacherNos).eq(Teacher::getSchoolId, importTeachingClass.getSchoolId()).eq(Teacher::getTerm, importTeachingClass.getTerm()).list()
                        .stream().collect(Collectors.toMap(Teacher::getBaseTeacherId, Teacher::getTeacherId));
            }
            if (CollUtil.isNotEmpty(allStudentNos)) {
                studentMap = studentService.lambdaQuery().in(Student::getBaseStudentId, allStudentNos).eq(Student::getTaskId, taskId).list()
                        .stream().collect(Collectors.toMap(Student::getBaseStudentId, Student::getStudentId));
            }
            //获取校区
            Map<String, String> campusMap = roomMapper.getCampusList(taskInfo.getSchoolId(), taskInfo.getTerm())
                    .stream().collect(Collectors.toMap(Campus::getCampusName, Campus::getCampusId));

            //遍历生成教学班 检验数据合理性
            for (int i = 0; i < addTeachingClass.size(); i++) {
                List<Long> teacherIds = new ArrayList<>();
                List<Long> studentIds = new ArrayList<>();
                Map<String, Object> map = addTeachingClass.get(i);
                String teachingClassName = map.get("teachingClassName").toString();
                String teacherNos = map.get("teacherNos").toString();
                String studentNos = map.get("studentNos").toString();
                String campusName = map.get("campusName").toString();
                //教学班名称
                if (StrUtil.isBlank(teachingClassName)) {
                    throw new BizException(5, "第" + (i + 3) + "行教学班名称不能为空");
                }
                //教师工号是否存在
                List<String> teacherNoList = Arrays.asList(teacherNos.split(","));
                for (String teacherNo : teacherNoList) {
                    if (teacherMap.containsKey(teacherNo)) {
                        teacherIds.add(teacherMap.get(teacherNo));
                    } else {
                        throw new BizException(5, "第" + (i + 3) + "行任课教师工号不存在:" + teacherNo);
                    }
                }
                //学生学号是否存在
                List<String> studentNoList = Arrays.asList(studentNos.split(","));
                for (String studentNo : studentNoList) {
                    if (studentMap.containsKey(studentNo)) {
                        studentIds.add(studentMap.get(studentNo));
                    } else {
                        throw new BizException(5, "第" + (i + 3) + "行上课对象学号不存在:" + studentNo);
                    }
                }
                if (StrUtil.isBlank(campusName)) {
                    throw new BizException(5, "第" + (i + 3) + "行校区名称不能为空");
                }
                if (!campusMap.containsKey(campusName)) {
                    throw new BizException(5, "第" + (i + 3) + "行校区名称不存在:" + campusName);
                }
                //todo 教学班名是否存在一样的
                teachingClassInputs.add(TeachingClassInput.builder()
                        .taskId(taskId)
                        .teachingClassName(teachingClassName)
                        .courseId(importTeachingClass.getCourseId())
                        .collegeId(importTeachingClass.getCollegeId())
                        .classNum(50)
                        .teachingClassType(0)
                        .flag(1)
                        .studyNature(importTeachingClass.getStudyNature())
                        .campusId(campusMap.get(campusName))
                        .campusName(campusName)
                        .isEnable(2)
//                        .teacherIds(teacherIds) todo修改导入模板
                        .studentIds(studentIds)
                        .build());
            }

            //删除该课程 非预选教学班数据
            List<Long> teachingClassId = this.lambdaQuery().eq(TeachingClass::getCourseId, importTeachingClass.getCourseId())
                    .eq(TeachingClass::getFlag, 1)
                    .ne(TeachingClass::getTeachingClassType, 3).list().stream()
                    .map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
            this.deleteClass(teachingClassId);

            this.addBatchTeachingClass(teachingClassInputs, false);
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
            throw new BizException(5, "导入教学班失败");
        }
        return true;
    }

    @Override
    public void teachTaskToExcel(Integer taskId, ServletOutputStream out) {
        List<List<Object>> rows = new ArrayList<>();
        //获取课程教学班信息
        List<ExcelTeachingClass> excelTeachingClass = teachingClassMapper.getExcelTeachingClass(taskId);
        if (CollUtil.isEmpty(excelTeachingClass)) {
            ExcelFormatUtil.writeRowsToExcel(rows, "教学任务模板.xlsx", 2, out);
            return;
        }
        List<Long> teachingClassIds = excelTeachingClass.stream().map(ExcelTeachingClass::getTeachingClassId).collect(Collectors.toList());
        //安排教室范围 roomId 获取roomName
        Map<Long, String> roomMap = new HashMap<>();
        List<Long> roomIds = excelTeachingClass.stream().map(ExcelTeachingClass::getRoomId)
                .filter(Objects::nonNull)
                .flatMap(roomIdString -> Arrays.stream(roomIdString.split(",")))
                .filter(StrUtil::isNotBlank)
                .map(Long::parseLong).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(roomIds)) {
            roomMap = roomService.lambdaQuery().in(Room::getRoomId, roomIds).list()
                    .stream().collect(Collectors.toMap(Room::getRoomId, Room::getRoomName));
        }
        //获取行政班
        Map<String, String> classMap = studentMapper.getClassDto(taskId, null, null, null)
                .stream().collect(Collectors.toMap(ClassDto::getClassId, ClassDto::getClassName));
        //获取上课对象
        Map<Long, List<ExcelStudent>> studentMap = studentMapper.getExcelStudent(teachingClassIds)
                .stream().collect(Collectors.groupingBy(ExcelStudent::getTeachingClassId));
        //获取教师信息
        Map<Long, List<Teacher>> teachingClassToTeacher = teacherService.getTeacherByTeachingClassIds(teachingClassIds).stream()
                .collect(Collectors.groupingBy(Teacher::getTeachingClassId));
        //获取教学班参数信息
        Map<Long, List<TeachingClassWeek>> weekMap = teachingClassWeekService.lambdaQuery().in(TeachingClassWeek::getTeachingClassId, teachingClassIds).list()
                .stream().collect(Collectors.groupingBy(TeachingClassWeek::getTeachingClassId));
        for (ExcelTeachingClass teachingClass : excelTeachingClass) {
            //上课对象字符串 C|2021级英语2班,2021级英语3班;S|stu036,stu037. 去掉已存行政班的学生
            String studentString = studentMap.getOrDefault(teachingClass.getTeachingClassId(), new ArrayList<>()).stream()
                    .filter(student -> !teachingClass.getToClass().contains(student.getClassId()))
                    .map(ExcelStudent::getBaseStudentId).collect(Collectors.joining(","));
            if (StrUtil.isNotBlank(studentString)) {
                studentString = "S|" + studentString;
            }
            if (StrUtil.isNotBlank(teachingClass.getToClass()) && StrUtil.isNotBlank(studentString)) {
                studentString = studentString + ";";
            }
            if (StrUtil.isNotBlank(teachingClass.getToClass())) {
                //行政班id转化为行政班名称
                String[] classIds = teachingClass.getToClass().split(",");
                String className = Arrays.stream(classIds).map(classMap::get).collect(Collectors.joining(","));
                studentString = studentString + "C|" + className;
            }
            //教师工号字符串
            String teachingString = ExcelFormatUtil.getTeacherNo(teachingClassToTeacher.get(teachingClass.getTeachingClassId()));
            //授课类型 相关数据
            weekMap.get(teachingClass.getTeachingClassId()).forEach(teachingClassWeek -> {
                if (teachingClassWeek.getHourType() == 1) {
                    teachingClass.setLectureWeek(teachingClassWeek.getWeek());
                    teachingClass.setLectureWeekNum(teachingClassWeek.getWeekNum());
                    teachingClass.setLectureConnectSection(teachingClassWeek.getConnectSection());
                    teachingClass.setLectureConnectNumber(teachingClassWeek.getConnectNumber());
                    teachingClass.setLectureRoomType(teachingClassWeek.getRoomType());
                } else if (teachingClassWeek.getHourType() == 2) {
                    teachingClass.setExperimentalWeek(teachingClassWeek.getWeek());
                    teachingClass.setExperimentalWeekNum(teachingClassWeek.getWeekNum());
                    teachingClass.setExperimentalConnectSection(teachingClassWeek.getConnectSection());
                    teachingClass.setExperimentalRoomType(teachingClassWeek.getRoomType());
                } else if (teachingClassWeek.getHourType() == 3) {
                    teachingClass.setComputerWeek(teachingClassWeek.getWeek());
                    teachingClass.setComputerWeekNum(teachingClassWeek.getWeekNum());
                    teachingClass.setComputerConnectSection(teachingClassWeek.getConnectSection());
                    teachingClass.setComputerRoomType(teachingClassWeek.getRoomType());
                } else if (teachingClassWeek.getHourType() == 4) {
                    teachingClass.setOtherWeek(teachingClassWeek.getWeek());
                    teachingClass.setOtherWeekNum(teachingClassWeek.getWeekNum());
                    teachingClass.setOtherConnectSection(teachingClassWeek.getConnectSection());
                    teachingClass.setOtherRoomType(teachingClassWeek.getRoomType());
                }
            });
            //教室字符串
            List<String> thisRoomNames = new ArrayList<>();
            for (String roomId : teachingClass.getRoomId().split(",")) {
                if (StrUtil.isNotBlank(roomId)) {
                    thisRoomNames.add(roomMap.get(Long.parseLong(roomId)));
                }
            }
            rows.add(Arrays.asList(
                    teachingClass.getTeachingClassName(),
                    teachingClass.getCourseName(),
                    studentString,
                    teachingClass.getIsSingle(),
                    teachingString,
                    teachingClass.getStudyNature().equals(1) ? "主修" : "辅修",
                    thisRoomNames.stream().filter(Objects::nonNull).collect(Collectors.joining(",")),
                    teachingClass.getCampusName(),
                    ObjUtil.isNotNull(teachingClass.getUniqueShiftSign()) ? 2 : 1,
                    ExcelFormatUtil.fromBinary(teachingClass.getLectureWeek()),
                    teachingClass.getLectureWeekNum(),
                    teachingClass.getLectureConnectSection(),
                    teachingClass.getLectureConnectNumber(),
                    teachingClass.getLectureRoomType(),
                    ExcelFormatUtil.fromBinary(teachingClass.getExperimentalWeek()),
                    teachingClass.getExperimentalWeekNum(),
                    teachingClass.getExperimentalConnectSection(),
                    teachingClass.getExperimentalRoomType(),
                    ExcelFormatUtil.fromBinary(teachingClass.getComputerWeek()),
                    teachingClass.getComputerWeekNum(),
                    teachingClass.getComputerConnectSection(),
                    teachingClass.getComputerRoomType(),
                    ExcelFormatUtil.fromBinary(teachingClass.getOtherWeek()),
                    teachingClass.getOtherWeekNum(),
                    teachingClass.getOtherConnectSection(),
                    teachingClass.getOtherRoomType()
            ));
        }
        //写入到输出流
        ExcelFormatUtil.writeRowsToExcel(rows, "教学任务模板.xlsx", 2, out);
    }

    @Override
    public FileImportInfo excelToTeachingTask(Integer taskId, MultipartFile file) {
        List<ExcelTeachingClass> excelTeachingClasses = this.readExcel(file);
        TaskInfo taskInfo = taskInfoService.getById(taskId);
        int totalWeek = TimeUtils.getTotalWeek(taskInfo.getTermBeginTime(), taskInfo.getTermEndTime()).intValue();
        //获取行政班
        Map<String, String> classMap = studentMapper.getClassDto(taskId, null, null, null)
                .stream().collect(Collectors.toMap(ClassDto::getClassName, ClassDto::getClassId));
        //获取课程信息
        List<String> courseNames = excelTeachingClasses.stream().map(ExcelTeachingClass::getCourseName).distinct().collect(Collectors.toList());
        Map<String, Course> courseMap = courseService.lambdaQuery().eq(Course::getTaskId, taskId).in(Course::getCourseName, courseNames).list()
                .stream().collect(Collectors.toMap(Course::getCourseName, course -> course));
        //获取学生信息
        Set<ExcelStudent> studentList = studentMapper.getStudentList(taskId);
        Map<String, List<ExcelStudent>> studentClassMap = studentList.stream().collect(Collectors.groupingBy(ExcelStudent::getClassId));
        Map<String, Long> studentIdMap = studentList.stream().collect(Collectors.toMap(ExcelStudent::getBaseStudentId, ExcelStudent::getStudentId));
        //获取教师信息
        Map<String, Long> teacherMap = new HashMap<>();
        List<String> teacherNos = excelTeachingClasses.stream().map(ExcelTeachingClass::getTeacherNo)
                .flatMap(teacherNo -> Arrays.stream(teacherNo.split("[,，]")))
                .map(String::trim)
                .distinct().collect(Collectors.toList());
        if (CollUtil.isNotEmpty(teacherNos)) {
            teacherMap = teacherService.lambdaQuery().eq(Teacher::getSchoolId, taskInfo.getSchoolId()).eq(Teacher::getTerm, taskInfo.getTerm()).in(Teacher::getBaseTeacherId, teacherNos).list()
                    .stream().collect(Collectors.toMap(Teacher::getBaseTeacherId, Teacher::getTeacherId));
        }
        //获取教室信息
        Map<String, Long> roomMap = new HashMap<>();
        List<String> roomNames = excelTeachingClasses.stream().map(ExcelTeachingClass::getRoomName)
                .flatMap(roomName -> Arrays.stream(roomName.split("[,，]")))
                .map(String::trim)
                .distinct().collect(Collectors.toList());
        if (CollUtil.isNotEmpty(roomNames)) {
            roomMap = roomService.lambdaQuery().eq(Room::getSchoolId, taskInfo.getSchoolId()).eq(Room::getTerm, taskInfo.getTerm()).in(Room::getRoomName, roomNames).list()
                    .stream().distinct().collect(Collectors.toMap(Room::getRoomName, Room::getRoomId));
        }
        //获取校区
        Map<String, String> campusMap = roomMapper.getCampusList(taskInfo.getSchoolId(), taskInfo.getTerm())
                .stream().collect(Collectors.toMap(Campus::getCampusName, Campus::getCampusId));
        //将分班教学班通过行政班分组
        Map<String, List<ExcelTeachingClass>> shiftMapByClass = new HashMap<>();
        //待插入数据 教学班 教学班对应学生 教学班对应教师 教学班参数设置
        List<TeachingClass> teachingClassList = new ArrayList<>();
        List<TeachingClassStudent> teachingClassStudentList = new ArrayList<>();
        List<TeachingClassTeacher> teachingClassTeacherList = new ArrayList<>();
        List<TeachingClassWeek> teachingClassWeekList = new ArrayList<>();
        //记录当前行数
        long index = 3;
        //错误日志
        List<Map<String, Object>> errorMapList = new ArrayList<>(excelTeachingClasses.size());
        StringJoiner stringJoiner;
        for (ExcelTeachingClass excelTeachingClass : excelTeachingClasses) {
            //存储当前教学班的行政班id
            List<String> classIdList = new ArrayList<>();
            //存储当前行唯一标识
            excelTeachingClass.setTeachingClassId(index);
            stringJoiner = new StringJoiner("\n");
            Map<String, String> studentObjectMap = formatStudentObject(excelTeachingClass.getStudentObject());
            if (!courseMap.containsKey(excelTeachingClass.getCourseName().trim())) {
                stringJoiner.add("第" + index + "行课程名称不存在:" + excelTeachingClass.getCourseName());
            }
            if (!campusMap.containsKey(excelTeachingClass.getCampusName().trim())) {
                stringJoiner.add("第" + index + "行校区名称不存在:" + excelTeachingClass.getCampusName());
            }
            //行政班名转化为行政班id
            String classNames = studentObjectMap.get("classIds");
            if (StrUtil.isNotBlank(classNames)) {
                for (String className : classNames.split("[,，]")) {
                    className = className.trim();
                    if (!classMap.containsKey(className)) {
                        stringJoiner.add("第" + index + "行行政班名称不存在:" + className);
                    } else {
                        classIdList.add(classMap.get(className));
                    }
                }
            }
            //转化roomIds
            for (String roomName : excelTeachingClass.getRoomName().split("[,，]")) {
                roomName = roomName.trim();
                if (StrUtil.isNotBlank(roomName)) {
                    if (!roomMap.containsKey(roomName)) {
                        stringJoiner.add("第" + index + "行教室名称不存在:" + roomName);
                    }
                }
            }
            //待插入教学班对应教师
            if (StrUtil.isNotBlank(excelTeachingClass.getTeacherNo())) {
                for (String teacherNo : excelTeachingClass.getTeacherNo().split("[,，]")) {
                    teacherNo = teacherNo.trim();
                    if (!teacherMap.containsKey(teacherNo)) {
                        stringJoiner.add("第" + index + "行教师编号不存在:" + teacherNo);
                    }
                }
            }
            //待插入教学班对应学生 该行政班学生及改学号学生
            String studentIds = studentObjectMap.get("studentIds");
            if (StrUtil.isNotBlank(studentIds)) {
                for (String studentId : studentIds.split("[,，]")) {
                    studentId = studentId.trim();
                    if (!studentIdMap.containsKey(studentId)) {
                        stringJoiner.add("第" + index + "行学生学号不存在:" + studentId);
                    }
                }
            }
            //分班教学班roomId不能为空
            if (StrUtil.isNotBlank(excelTeachingClass.getUniqueShiftSign()) && "2".equals(excelTeachingClass.getUniqueShiftSign())) {
                if (StrUtil.isBlank(excelTeachingClass.getRoomName())) {
                    stringJoiner.add("第" + excelTeachingClass.getTeachingClassId() + "行分班教学班必须指定教室");
                }
                classIdList.forEach(classId -> {
                    if (!shiftMapByClass.containsKey(classId)) {
                        shiftMapByClass.put(classId, new ArrayList<>());
                    }
                    shiftMapByClass.get(classId).add(excelTeachingClass);
                });
            }

            if (stringJoiner.toString().length() == 0) {
                //行政班名转化为行政班id
                String classIds = "";
                if (StrUtil.isNotBlank(classNames)) {
                    for (String className : classNames.split("[,，]")) {
                        className = className.trim();
                        for (ExcelStudent excelStudent : studentClassMap.get(classMap.get(className))) {
                            String baseStudentId = excelStudent.getBaseStudentId();
                            //根据学生单双号判断是否添加该学生
                            boolean isAdd = ObjUtil.isNull(excelTeachingClass.getIsSingle()) ||
                                    (int) (baseStudentId.charAt(baseStudentId.length() - 1)) % 2 == excelTeachingClass.getIsSingle() % 2;
                            if (!isAdd) {
                                teachingClassStudentList.add(new TeachingClassStudent().setTeachingClassId(index)
                                        .setStudentId(excelStudent.getStudentId())
                                        .setFlag(1));
                            }
                        }
                        classIds += classMap.get(className) + ",";
                    }
                }
                if (StrUtil.isNotBlank(classIds)) {
                    classIds = classIds.substring(0, classIds.length() - 1);
                }
                //转化roomIds
                String roomIds = "";
                for (String roomName : excelTeachingClass.getRoomName().split("[,，]")) {
                    roomName = roomName.trim();
                    if (StrUtil.isNotBlank(roomName)) {
                        roomIds += roomMap.get(roomName) + ",";
                    }
                }
                if (StrUtil.isNotBlank(roomIds)) {
                    roomIds = roomIds.substring(0, roomIds.length() - 1);
                }
                //待插入教学班
                teachingClassList.add(new TeachingClass().setTaskId(taskId)
                        .setTeachingClassName(excelTeachingClass.getTeachingClassName())
                        .setCourseId(courseMap.get(excelTeachingClass.getCourseName()).getCourseId())
                        .setCollegeId(courseMap.get(excelTeachingClass.getCourseName()).getCollegeId())
                        .setToClass(classIds)
                        .setTeachingClassType(0)
                        .setFlag(1)
                        .setRoomId(roomIds)
                        .setStudyNature("主修".equals(excelTeachingClass.getStudyNature()) ? 1 : 2)
                        .setCampusId(campusMap.get(excelTeachingClass.getCampusName()))
                        .setCampusName(excelTeachingClass.getCampusName())
                        .setUniqueShiftSign(StrUtil.isBlank(excelTeachingClass.getUniqueShiftSign()) || "1".equals(excelTeachingClass.getUniqueShiftSign()) ? null : classIds)
                        .setIsSingle(excelTeachingClass.getIsSingle())
                        //记录行数作为当前导入唯一标识 用于插入数据库后关联id
                        .setStudentNumber((int) index));
                //待插入教学班对应教师
                if (StrUtil.isNotBlank(excelTeachingClass.getTeacherNo())) {
                    for (String teacherNo : excelTeachingClass.getTeacherNo().split("[,，]")) {
                        teacherNo = teacherNo.trim(); // 去除空格
                        teachingClassTeacherList.add(new TeachingClassTeacher().setTeachingClassId(index)
                                .setTeacherId(teacherMap.get(teacherNo))
                                .setTeacherType(0));
                    }
                }
                //待插入教学班对应学生 该行政班学生及改学号学生
                if (StrUtil.isNotBlank(studentIds)) {
                    for (String studentId : studentIds.split("[,，]")) {
                        studentId = studentId.trim();
                        teachingClassStudentList.add(new TeachingClassStudent().setTeachingClassId(index)
                                .setStudentId(studentIdMap.get(studentId))
                                .setFlag(1));

                    }
                }
                //待插入教学班参数设置
                if (StrUtil.isNotBlank(excelTeachingClass.getLectureWeek())) {
                    teachingClassWeekList.add(new TeachingClassWeek().setTeachingClassId(index)
                            .setWeek(ExcelFormatUtil.toBinary(excelTeachingClass.getLectureWeek(), totalWeek))
                            .setWeekNum(excelTeachingClass.getLectureWeekNum())
                            .setConnectSection(excelTeachingClass.getLectureConnectSection() == null ? 1 : excelTeachingClass.getLectureConnectSection())
                            .setConnectNumber(excelTeachingClass.getLectureConnectNumber() == null ? 0 : excelTeachingClass.getLectureConnectNumber())
                            .setRoomType(excelTeachingClass.getLectureRoomType())
                            .setHourType(1));
                }
                if (StrUtil.isNotBlank(excelTeachingClass.getExperimentalWeek())) {
                    teachingClassWeekList.add(new TeachingClassWeek().setTeachingClassId(index)
                            .setWeek(ExcelFormatUtil.toBinary(excelTeachingClass.getExperimentalWeek(), totalWeek))
                            .setWeekNum(excelTeachingClass.getExperimentalWeekNum())
                            .setConnectSection(excelTeachingClass.getExperimentalConnectSection() == null ? 1 : excelTeachingClass.getExperimentalConnectSection())
                            .setConnectNumber(0)
                            .setRoomType(excelTeachingClass.getExperimentalRoomType())
                            .setHourType(2));
                }
                if (StrUtil.isNotBlank(excelTeachingClass.getComputerWeek())) {
                    teachingClassWeekList.add(new TeachingClassWeek().setTeachingClassId(index)
                            .setWeek(ExcelFormatUtil.toBinary(excelTeachingClass.getComputerWeek(), totalWeek))
                            .setWeekNum(excelTeachingClass.getComputerWeekNum())
                            .setConnectSection(excelTeachingClass.getComputerConnectSection() == null ? 1 : excelTeachingClass.getComputerConnectSection())
                            .setConnectNumber(0)
                            .setRoomType(excelTeachingClass.getComputerRoomType())
                            .setHourType(3));
                }
                if (StrUtil.isNotBlank(excelTeachingClass.getOtherWeek())) {
                    teachingClassWeekList.add(new TeachingClassWeek().setTeachingClassId(index)
                            .setWeek(ExcelFormatUtil.toBinary(excelTeachingClass.getOtherWeek(), totalWeek))
                            .setWeekNum(excelTeachingClass.getOtherWeekNum())
                            .setConnectSection(excelTeachingClass.getOtherConnectSection() == null ? 1 : excelTeachingClass.getOtherConnectSection())
                            .setConnectNumber(0)
                            .setRoomType(excelTeachingClass.getOtherRoomType())
                            .setHourType(4));
                }
            } else {
                Map<String, Object> errorMap = new LinkedHashMap<>(2);
                errorMap.put("原Excel行号", index);
                errorMap.put("错误原因", stringJoiner.toString());
                errorMapList.add(errorMap);
            }
            index++;
        }
        //判断分班教学班组合是否合理
        shiftMapByClass.values().forEach(teachingClass -> {
            //行号
            String lines = teachingClass.stream().map(a -> a.getTeachingClassId().toString()).collect(Collectors.joining(","));
            StringJoiner shitError = getShitError(teachingClass);
            if (StrUtil.isNotBlank(shitError.toString())) {
                Map<String, Object> errorMap = new LinkedHashMap<>(2);
                errorMap.put("原Excel行号", lines);
                errorMap.put("错误原因", shitError.toString());
                errorMapList.add(errorMap);
            }
        });
        //返回实体类
        FileImportInfo fileImportInfo = FileImportInfo.builder()
                .errorImportFilePath("")
                .failureImportNum(errorMapList.size())
                .successImportNum(excelTeachingClasses.size() - errorMapList.size())
                .build();
        if (errorMapList.size() > 0) {
            String storePath = "/" + taskInfo.getTaskName() + "/导入教学班错误信息-" + LocalDate.now() + ".xlsx";
            String targetPath = GlobalConstant.OUTPUT_EXCEL_PATH + storePath;

            FileUtil.del(targetPath);
            ExcelWriter writer = ExcelUtil.getWriter(targetPath, "导入教学班错误信息");
            writer.write(errorMapList, true);
            writer.close();
            fileImportInfo.setErrorImportFilePath(GlobalConstant.ACCESS_PATH + "/static/OutputExcel" + storePath);
        }
        //插入教学班
        if (StrUtil.isBlank(fileImportInfo.getErrorImportFilePath())) {
            batchInsert(taskId, teachingClassList, teachingClassTeacherList, teachingClassStudentList, teachingClassWeekList, null);
        }
        return fileImportInfo;
    }

    @Override
    public FileImportInfo excelToTeachingTaskAll(Integer taskId, MultipartFile file) {
        List<ExcelTeachingClassAll> excelTeachingClasses = this.readExcelAll(file);
        TaskInfo taskInfo = taskInfoService.getById(taskId);
        int totalWeek = TimeUtils.getTotalWeek(taskInfo.getTermBeginTime(), taskInfo.getTermEndTime()).intValue();
        //获取行政班
        Map<String, String> classMap = studentMapper.getClassDto(taskId, null, null, null)
                .stream().collect(Collectors.toMap(ClassDto::getClassName, ClassDto::getClassId));
        //获取课程信息
        List<String> courseNames = excelTeachingClasses.stream().map(ExcelTeachingClassAll::getCourseName).distinct().collect(Collectors.toList());
        Map<String, Course> courseMap = courseService.lambdaQuery().eq(Course::getTaskId, taskId).in(Course::getCourseName, courseNames).list()
                .stream().collect(Collectors.toMap(Course::getCourseName, course -> course));
        //获取学生信息
        Set<ExcelStudent> studentList = studentMapper.getStudentList(taskId);
        Map<String, List<ExcelStudent>> studentClassMap = studentList.stream().collect(Collectors.groupingBy(ExcelStudent::getClassId));
        Map<String, Long> studentIdMap = studentList.stream().collect(Collectors.toMap(ExcelStudent::getBaseStudentId, ExcelStudent::getStudentId));
        //获取教师信息
        Map<String, Long> teacherMap = new HashMap<>();
        HashSet<String> teacherNos = new HashSet<>();
        teacherNos.addAll(excelTeachingClasses.stream().map(ExcelTeachingClassAll::getLectureTeacher)
                .filter(o -> StrUtil.isNotBlank(o))
                .flatMap(teacherNo -> Arrays.stream(teacherNo.split("[,，]")))
                .map(String::trim)
                .distinct().collect(Collectors.toList()));
        teacherNos.addAll(excelTeachingClasses.stream().map(ExcelTeachingClassAll::getExperimentalTeacher)
                .filter(o -> StrUtil.isNotBlank(o))
                .flatMap(teacherNo -> Arrays.stream(teacherNo.split("[,，]")))
                .map(String::trim)
                .distinct().collect(Collectors.toList()));
        teacherNos.addAll(excelTeachingClasses.stream().map(ExcelTeachingClassAll::getComputerTeacher)
                .filter(o -> StrUtil.isNotBlank(o))
                .flatMap(teacherNo -> Arrays.stream(teacherNo.split("[,，]")))
                .map(String::trim)
                .distinct().collect(Collectors.toList()));
        teacherNos.addAll(excelTeachingClasses.stream().map(ExcelTeachingClassAll::getOtherTeacher)
                .filter(o -> StrUtil.isNotBlank(o))
                .flatMap(teacherNo -> Arrays.stream(teacherNo.split("[,，]")))
                .map(String::trim)
                .distinct().collect(Collectors.toList()));
        if (CollUtil.isNotEmpty(teacherNos)) {
            teacherMap = teacherService.lambdaQuery().eq(Teacher::getSchoolId, taskInfo.getSchoolId()).eq(Teacher::getTerm, taskInfo.getTerm()).in(Teacher::getBaseTeacherId, teacherNos).list()
                    .stream().collect(Collectors.toMap(Teacher::getBaseTeacherId, Teacher::getTeacherId));
        }
        //获取教室信息
        Map<String, Room> roomMap = new HashMap<>();
        HashSet<String> roomNames = new HashSet<>();
        roomNames.addAll(excelTeachingClasses.stream().map(ExcelTeachingClassAll::getLectureRoomName)
                .distinct().collect(Collectors.toList()));
        roomNames.addAll(excelTeachingClasses.stream().map(ExcelTeachingClassAll::getExperimentalRoomName)
                .distinct().collect(Collectors.toList()));
        roomNames.addAll(excelTeachingClasses.stream().map(ExcelTeachingClassAll::getComputerRoomName)
                .distinct().collect(Collectors.toList()));
        roomNames.addAll(excelTeachingClasses.stream().map(ExcelTeachingClassAll::getOtherRoomName)
                .distinct().collect(Collectors.toList()));
        if (CollUtil.isNotEmpty(roomNames)) {
            roomMap = roomService.lambdaQuery().eq(Room::getSchoolId, taskInfo.getSchoolId()).eq(Room::getTerm, taskInfo.getTerm()).in(Room::getRoomName, roomNames).list()
                    .stream().distinct().collect(Collectors.toMap(Room::getRoomName, o -> o));
        }
        //获取校区
        Map<String, String> campusMap = roomMapper.getCampusList(taskInfo.getSchoolId(), taskInfo.getTerm())
                .stream().collect(Collectors.toMap(Campus::getCampusName, Campus::getCampusId));
        //待插入数据 教学班 教学班对应学生 教学班对应教师 教学班参数设置
        List<TeachingClass> teachingClassList = new ArrayList<>();
        List<TeachingClassStudent> teachingClassStudentList = new ArrayList<>();
        List<TeachingClassTeacher> teachingClassTeacherList = new ArrayList<>();
        List<TeachingClassWeek> teachingClassWeekList = new ArrayList<>();
        //记录当前行数
        long index = 3;
        //错误日志
        List<Map<String, Object>> errorMapList = new ArrayList<>(excelTeachingClasses.size());
        StringJoiner stringJoiner;
        for (ExcelTeachingClassAll excelTeachingClass : excelTeachingClasses) {
            //存储当前教学班的行政班id
            List<String> classIdList = new ArrayList<>();
            //存储当前行唯一标识
            excelTeachingClass.setTeachingClassId(index);
            stringJoiner = new StringJoiner("\n");
            Map<String, String> studentObjectMap = formatStudentObject(excelTeachingClass.getStudentObject());
            if (!courseMap.containsKey(excelTeachingClass.getCourseName().trim())) {
                stringJoiner.add("第" + index + "行课程名称不存在:" + excelTeachingClass.getCourseName());
            }
            if (!campusMap.containsKey(excelTeachingClass.getCampusName().trim())) {
                stringJoiner.add("第" + index + "行校区名称不存在:" + excelTeachingClass.getCampusName());
            }
            //行政班名转化为行政班id
            String classNames = studentObjectMap.get("classIds");
            if (StrUtil.isNotBlank(classNames)) {
                for (String className : classNames.split("[,，]")) {
                    className = className.trim();
                    if (!classMap.containsKey(className)) {
                        stringJoiner.add("第" + index + "行行政班名称不存在:" + className);
                    } else {
                        classIdList.add(classMap.get(className));
                    }
                }
            }
            //转化roomIds
            String roomName = excelTeachingClass.getLectureRoomName();
            if (StrUtil.isNotBlank(roomName)) {
                if (!roomMap.containsKey(roomName.trim())) {
                    stringJoiner.add("第" + index + "行教室名称不存在:" + roomName);
                }
            }
            roomName = excelTeachingClass.getExperimentalRoomName();
            if (StrUtil.isNotBlank(roomName)) {
                if (!roomMap.containsKey(roomName.trim())) {
                    stringJoiner.add("第" + index + "行教室名称不存在:" + roomName);
                }
            }
            roomName = excelTeachingClass.getComputerRoomName();
            if (StrUtil.isNotBlank(roomName)) {
                if (!roomMap.containsKey(roomName.trim())) {
                    stringJoiner.add("第" + index + "行教室名称不存在:" + roomName);
                }
            }
            roomName = excelTeachingClass.getOtherRoomName();
            if (StrUtil.isNotBlank(roomName)) {
                if (!roomMap.containsKey(roomName.trim())) {
                    stringJoiner.add("第" + index + "行教室名称不存在:" + roomName);
                }
            }

            //待插入教学班对应教师
            if (StrUtil.isNotBlank(excelTeachingClass.getLectureTeacher())) {
                for (String teacherNo : excelTeachingClass.getLectureTeacher().split("[,，]")) {
                    teacherNo = teacherNo.trim();
                    if (!teacherMap.containsKey(teacherNo)) {
                        stringJoiner.add("第" + index + "行教师编号不存在:" + teacherNo);
                    }
                }
            }
            if (StrUtil.isNotBlank(excelTeachingClass.getExperimentalTeacher())) {
                for (String teacherNo : excelTeachingClass.getExperimentalTeacher().split("[,，]")) {
                    teacherNo = teacherNo.trim();
                    if (!teacherMap.containsKey(teacherNo)) {
                        stringJoiner.add("第" + index + "行教师编号不存在:" + teacherNo);
                    }
                }
            }
            if (StrUtil.isNotBlank(excelTeachingClass.getComputerTeacher())) {
                for (String teacherNo : excelTeachingClass.getComputerTeacher().split("[,，]")) {
                    teacherNo = teacherNo.trim();
                    if (!teacherMap.containsKey(teacherNo)) {
                        stringJoiner.add("第" + index + "行教师编号不存在:" + teacherNo);
                    }
                }
            }
            if (StrUtil.isNotBlank(excelTeachingClass.getOtherTeacher())) {
                for (String teacherNo : excelTeachingClass.getOtherTeacher().split("[,，]")) {
                    teacherNo = teacherNo.trim();
                    if (!teacherMap.containsKey(teacherNo)) {
                        stringJoiner.add("第" + index + "行教师编号不存在:" + teacherNo);
                    }
                }
            }

            //待插入教学班对应学生 该行政班学生及改学号学生
            String studentIds = studentObjectMap.get("studentIds");
            if (StrUtil.isNotBlank(studentIds)) {
                for (String studentId : studentIds.split("[,，]")) {
                    studentId = studentId.trim();
                    if (!studentIdMap.containsKey(studentId)) {
                        stringJoiner.add("第" + index + "行学生学号不存在:" + studentId);
                    }
                }
            }

            if (stringJoiner.toString().length() == 0) {
                //行政班名转化为行政班id
                String classIds = "";
                int classNum = 0;
                if (StrUtil.isNotBlank(classNames)) {
                    for (String className : classNames.split("[,，]")) {
                        className = className.trim();
                        for (ExcelStudent excelStudent : studentClassMap.get(classMap.get(className))) {
                            teachingClassStudentList.add(new TeachingClassStudent().setTeachingClassId(index)
                                    .setStudentId(excelStudent.getStudentId())
                                    .setFlag(1));
                            classNum++;
                        }
                        classIds += classMap.get(className) + ",";
                    }
                }
                if (StrUtil.isNotBlank(classIds)) {
                    classIds = classIds.substring(0, classIds.length() - 1);
                }

                //待插入教学班
                teachingClassList.add(new TeachingClass().setTaskId(taskId)
                        .setTeachingClassName(excelTeachingClass.getTeachingClassName())
                        .setCourseId(courseMap.get(excelTeachingClass.getCourseName()).getCourseId())
                        .setCourseName(excelTeachingClass.getCourseName())
                        .setCollegeId(courseMap.get(excelTeachingClass.getCourseName()).getCollegeId())
                        .setClassNum(classNum)
                        .setToClass(classIds)
                        .setTeachingClassType(0)
                        .setFlag(1)
                        .setStudyNature("主修".equals(excelTeachingClass.getStudyNature()) ? 1 : 2)
                        .setCampusId(campusMap.get(excelTeachingClass.getCampusName()))
                        .setCampusName(excelTeachingClass.getCampusName())
                        //记录行数作为当前导入唯一标识 用于插入数据库后关联id
                        .setStudentNumber((int) index));
                //待插入教学班对应教师
                if (StrUtil.isNotBlank(excelTeachingClass.getLectureTeacher())) {
                    for (String teacherNo : excelTeachingClass.getLectureTeacher().split("[,，]")) {
                        teacherNo = teacherNo.trim(); // 去除空格
                        Long tId = teacherMap.get(teacherNo);
                        long finalIndex1 = index;
                        if(teachingClassTeacherList.stream().noneMatch(o -> o.getTeachingClassId() == finalIndex1
                                && o.getTeacherId().equals(tId) &&  o.getHourType() == 1)){
                            teachingClassTeacherList.add(new TeachingClassTeacher().setTeachingClassId(index)
                                    .setTeacherId(tId)
                                    .setTeacherType(0)
                                    .setHourType(1));
                        }
                    }
                }
                if (StrUtil.isNotBlank(excelTeachingClass.getExperimentalTeacher())) {
                    for (String teacherNo : excelTeachingClass.getExperimentalTeacher().split("[,，]")) {
                        teacherNo = teacherNo.trim(); // 去除空格
                        Long tId = teacherMap.get(teacherNo);
                        long finalIndex1 = index;
                        if(teachingClassTeacherList.stream().noneMatch(o -> o.getTeachingClassId() == finalIndex1
                                && o.getTeacherId().equals(tId) &&  o.getHourType() == 2)){
                            teachingClassTeacherList.add(new TeachingClassTeacher().setTeachingClassId(index)
                                    .setTeacherId(tId)
                                    .setTeacherType(0)
                                    .setHourType(2));
                        }
                    }
                }
                if (StrUtil.isNotBlank(excelTeachingClass.getComputerTeacher())) {
                    for (String teacherNo : excelTeachingClass.getComputerTeacher().split("[,，]")) {
                        teacherNo = teacherNo.trim(); // 去除空格
                        Long tId = teacherMap.get(teacherNo);
                        long finalIndex1 = index;
                        if(teachingClassTeacherList.stream().noneMatch(o -> o.getTeachingClassId() == finalIndex1
                                && o.getTeacherId().equals(tId) &&  o.getHourType() == 3)){
                            teachingClassTeacherList.add(new TeachingClassTeacher().setTeachingClassId(index)
                                    .setTeacherId(tId)
                                    .setTeacherType(0)
                                    .setHourType(3));
                        }
                    }
                }
                if (StrUtil.isNotBlank(excelTeachingClass.getOtherTeacher())) {
                    for (String teacherNo : excelTeachingClass.getOtherTeacher().split("[,，]")) {
                        teacherNo = teacherNo.trim(); // 去除空格
                        Long tId = teacherMap.get(teacherNo);
                        long finalIndex1 = index;
                        if(teachingClassTeacherList.stream().noneMatch(o -> o.getTeachingClassId() == finalIndex1
                                && o.getTeacherId().equals(tId) &&  o.getHourType() == 4)){
                            teachingClassTeacherList.add(new TeachingClassTeacher().setTeachingClassId(index)
                                    .setTeacherId(tId)
                                    .setTeacherType(0)
                                    .setHourType(4));
                        }
                    }
                }



                //待插入教学班对应学生 该行政班学生及改学号学生
                if (StrUtil.isNotBlank(studentIds)) {
                    for (String studentId : studentIds.split("[,，]")) {
                        studentId = studentId.trim();
                        Long stuId = studentIdMap.get(studentId);
                        long finalIndex = index;
                        if(teachingClassStudentList.stream().noneMatch(o -> o.getTeachingClassId() == finalIndex
                                && o.getStudentId().equals(stuId))){
                            teachingClassStudentList.add(new TeachingClassStudent().setTeachingClassId(index)
                                    .setStudentId(stuId)
                                    .setFlag(1));
                        }

                    }
                }
                //待插入教学班参数设置
                if (StrUtil.isNotBlank(excelTeachingClass.getLectureWeek())) {
                    //转化roomIds
                    Room room = null;
                    roomName = excelTeachingClass.getLectureRoomName().trim();
                    if (StrUtil.isNotBlank(roomName)) {
                        room = roomMap.get(roomName);
                    }

                    teachingClassWeekList.add(new TeachingClassWeek().setTeachingClassId(index)
                            .setWeek(ExcelFormatUtil.toBinary(excelTeachingClass.getLectureWeek(), totalWeek))
                            .setWeekNum(excelTeachingClass.getLectureWeekNum())
                            .setConnectSection(excelTeachingClass.getLectureConnectSection() == null ? 1 : excelTeachingClass.getLectureConnectSection())
                            .setConnectNumber(excelTeachingClass.getLectureConnectNumber() == null ? 0 : excelTeachingClass.getLectureConnectNumber())
                            .setRoomType(room == null ? excelTeachingClass.getLectureRoomType() : room.getRoomType())
                            .setRoomId(room == null ? null : room.getRoomId())
                            .setHourType(1));
                }
                if (StrUtil.isNotBlank(excelTeachingClass.getExperimentalWeek())) {
                    //转化roomIds
                    Room room = null;
                    roomName = excelTeachingClass.getExperimentalRoomName().trim();
                    if (StrUtil.isNotBlank(roomName)) {
                        room = roomMap.get(roomName);
                    }

                    teachingClassWeekList.add(new TeachingClassWeek().setTeachingClassId(index)
                            .setWeek(ExcelFormatUtil.toBinary(excelTeachingClass.getExperimentalWeek(), totalWeek))
                            .setWeekNum(excelTeachingClass.getExperimentalWeekNum())
                            .setConnectSection(excelTeachingClass.getExperimentalConnectSection() == null ? 1 : excelTeachingClass.getExperimentalConnectSection())
                            .setConnectNumber(excelTeachingClass.getExperimentalConnectNumber() == null ? 0 : excelTeachingClass.getExperimentalConnectNumber())
                            .setRoomType(room == null ? excelTeachingClass.getExperimentalRoomType() : room.getRoomType())
                            .setRoomId(room == null ? null : room.getRoomId())
                            .setHourType(2));
                }
                if (StrUtil.isNotBlank(excelTeachingClass.getComputerWeek())) {
                    Room room = null;
                    roomName = excelTeachingClass.getComputerRoomName().trim();
                    if (StrUtil.isNotBlank(roomName)) {
                        room = roomMap.get(roomName);
                    }
                    teachingClassWeekList.add(new TeachingClassWeek().setTeachingClassId(index)
                            .setWeek(ExcelFormatUtil.toBinary(excelTeachingClass.getComputerWeek(), totalWeek))
                            .setWeekNum(excelTeachingClass.getComputerWeekNum())
                            .setConnectSection(excelTeachingClass.getComputerConnectSection() == null ? 1 : excelTeachingClass.getComputerConnectSection())
                            .setConnectNumber(excelTeachingClass.getComputerConnectNumber() == null ? 0 : excelTeachingClass.getComputerConnectNumber())
                            .setRoomType(room == null ? excelTeachingClass.getComputerRoomType() : room.getRoomType())
                            .setRoomId(room == null ? null : room.getRoomId())
                            .setHourType(3));
                }
                if (StrUtil.isNotBlank(excelTeachingClass.getOtherWeek())) {
                    Room room = null;
                    roomName = excelTeachingClass.getOtherRoomName().trim();
                    if (StrUtil.isNotBlank(roomName)) {
                        room = roomMap.get(roomName);
                    }
                    teachingClassWeekList.add(new TeachingClassWeek().setTeachingClassId(index)
                            .setWeek(ExcelFormatUtil.toBinary(excelTeachingClass.getOtherWeek(), totalWeek))
                            .setWeekNum(excelTeachingClass.getOtherWeekNum())
                            .setConnectSection(excelTeachingClass.getOtherConnectSection() == null ? 1 : excelTeachingClass.getOtherConnectSection())
                            .setConnectNumber(excelTeachingClass.getOtherConnectNumber() == null ? 0 : excelTeachingClass.getOtherConnectNumber())
                            .setRoomType(room == null ? excelTeachingClass.getOtherRoomType() : room.getRoomType())
                            .setRoomId(room == null ? null : room.getRoomId())
                            .setHourType(4));
                }
            } else {
                Map<String, Object> errorMap = new LinkedHashMap<>(2);
                errorMap.put("原Excel行号", index);
                errorMap.put("错误原因", stringJoiner.toString());
                errorMapList.add(errorMap);
            }
            index++;
        }

        //返回实体类
        FileImportInfo fileImportInfo = FileImportInfo.builder()
                .errorImportFilePath("")
                .failureImportNum(errorMapList.size())
                .successImportNum(excelTeachingClasses.size() - errorMapList.size())
                .build();
        if (errorMapList.size() > 0) {
            String storePath = "/" + taskInfo.getTaskName() + "/导入教学班错误信息-" + LocalDate.now() + ".xlsx";
            String targetPath = GlobalConstant.OUTPUT_EXCEL_PATH + storePath;

            FileUtil.del(targetPath);
            ExcelWriter writer = ExcelUtil.getWriter(targetPath, "导入教学班错误信息");
            writer.write(errorMapList, true);
            writer.close();
            fileImportInfo.setErrorImportFilePath(GlobalConstant.ACCESS_PATH + "/static/OutputExcel" + storePath);
        }
        //插入教学班
        if (CollUtil.isNotEmpty(teachingClassList) && CollUtil.isNotEmpty(teachingClassWeekList)) {
            batchInsert(taskId, teachingClassList, teachingClassTeacherList, teachingClassStudentList, teachingClassWeekList, new ArrayList<>());
        }
        return fileImportInfo;
    }

    /**
     * 根据一个行政班的教学班 判断分班教学班是否合理
     *
     * @param teachingClass
     * @return
     */
    public StringJoiner getShitError(List<ExcelTeachingClass> teachingClass) {
        StringJoiner joiner = new StringJoiner("\n");
        //周次必须都一样
        if (teachingClass.stream().map(ExcelTeachingClass::getLectureWeek).distinct().count() != 1) {
            joiner.add("分班教学班周次不一致");
        }
        //根据课程名 教室名分组，一条数据类似前端一个课程
        Map<String, List<ExcelTeachingClass>> groupCourse = teachingClass.stream().collect(Collectors.groupingBy(a -> a.getCourseName() + "-" + a.getRoomName()));
        List<ExcelTeachingClass> courseList = new ArrayList<>();
        //判断每个课程生成的教学班是否符合要求
        groupCourse.values().forEach(group -> {
            if (group.size() != 2) {
                joiner.add("该分班课程须保证有两个教学班：" + group.get(0).getCourseName());
            } else {
                ExcelTeachingClass first = group.get(0);
                ExcelTeachingClass second = group.get(1);
                if (!Objects.equals(first.getLectureWeekNum(), second.getLectureWeekNum())) {
                    joiner.add("该分班课程周学时不相等" + first.getCourseName());
                }
                if (Objects.equals(first.getIsSingle(), second.getIsSingle())) {
                    joiner.add("该分班课程须确保包含单双号学生" + first.getCourseName());
                }
                courseList.add(first);
            }

        });
        //周学时 满足最大的小于其余总和
        int maxWeekNum = courseList.stream().mapToInt(ExcelTeachingClass::getLectureWeekNum).max().orElse(0);
        int sumOfOtherWeeks = courseList.stream().mapToInt(ExcelTeachingClass::getLectureWeekNum).sum() - maxWeekNum;
        if (maxWeekNum > sumOfOtherWeeks) {
            joiner.add("最大周学时不小于其他周学时之和");
        }
        return joiner;
    }

    @Override
    public FileImportInfo excelToSubClass(Integer taskId, MultipartFile file) {
        List<ExcelSubClass> excelTeachingClasses = this.readSubClassExcel(file);
        TaskInfo taskInfo = taskInfoService.getById(taskId);
        int totalWeek = TimeUtils.getTotalWeek(taskInfo.getTermBeginTime(), taskInfo.getTermEndTime()).intValue();
        //获取行政班
        Map<String, ClassDto> classMap = studentMapper.getClassDto(taskId, null, null, null)
                .stream().collect(Collectors.toMap(ClassDto::getClassName, classDto -> classDto));
        //获取课程信息
        List<String> courseNames = excelTeachingClasses.stream().map(ExcelSubClass::getCourseName).distinct().collect(Collectors.toList());
        Map<String, Course> courseMap = courseService.lambdaQuery().eq(Course::getTaskId, taskId).in(Course::getCourseName, courseNames).list()
                .stream().collect(Collectors.toMap(Course::getCourseName, course -> course));
        //获取学生信息
        Set<ExcelStudent> studentList = studentMapper.getStudentList(taskId);
        Map<String, List<ExcelStudent>> studentClassMap = studentList.stream().collect(Collectors.groupingBy(ExcelStudent::getClassId));
        Map<String, Long> studentIdMap = studentList.stream().collect(Collectors.toMap(ExcelStudent::getBaseStudentId, ExcelStudent::getStudentId));
        //获取教师信息
        Map<String, Long> teacherMap = new HashMap<>();
        List<String> teacherNos = excelTeachingClasses.stream()
                .flatMap(excelSubClass -> Stream.of(excelSubClass.getLectureTeacherNo(), excelSubClass.getExperimentalTeacherNo(),excelSubClass.getComputerTeacherNo(),excelSubClass.getOtherTeacherNo()))
                .filter(StrUtil::isNotBlank)
                .flatMap(teacherNo -> Arrays.stream(teacherNo.split("[,，]")))
                .map(String::trim)
                .distinct().collect(Collectors.toList());
        if (CollUtil.isNotEmpty(teacherNos)) {
            teacherMap = teacherService.lambdaQuery().eq(Teacher::getSchoolId, taskInfo.getSchoolId()).eq(Teacher::getTerm, taskInfo.getTerm()).in(Teacher::getBaseTeacherId, teacherNos).list()
                    .stream().collect(Collectors.toMap(Teacher::getBaseTeacherId, Teacher::getTeacherId));
        }
        //获取教室信息
        Map<String, Long> roomMap = new HashMap<>();
        List<String> roomNames = excelTeachingClasses.stream()
                .flatMap(a -> Stream.of(a.getLectureRoomName(), a.getExperimentalRoomName(), a.getComputerRoomName(), a.getOtherRoomName()))
                .distinct().collect(Collectors.toList());
        if (CollUtil.isNotEmpty(roomNames)) {
            roomMap = roomService.lambdaQuery().eq(Room::getSchoolId, taskInfo.getSchoolId()).eq(Room::getTerm, taskInfo.getTerm()).in(Room::getRoomName, roomNames).list()
                    .stream().distinct().collect(Collectors.toMap(Room::getRoomName, Room::getRoomId));
        }
        //获取校区
        Map<String, String> campusMap = roomMapper.getCampusList(taskInfo.getSchoolId(), taskInfo.getTerm())
                .stream().collect(Collectors.toMap(Campus::getCampusName, Campus::getCampusId));
        //将分班教学班通过行政班分组
        Map<String, List<ExcelTeachingClass>> shiftMapByClass = new HashMap<>();
        //待插入数据 教学班 教学班对应学生 教学班对应教师 教学班参数设置
        List<TeachingClass> teachingClassList = new ArrayList<>();
        List<TeachingClassStudent> teachingClassStudentList = new ArrayList<>();
        List<TeachingClassTeacher> teachingClassTeacherList = new ArrayList<>();
        List<TeachingClassWeek> teachingClassWeekList = new ArrayList<>();
        List<SubClass> subClassList = new ArrayList<>();
        //记录当前行数
        long index = 3;
        for (ExcelSubClass excelTeachingClass : excelTeachingClasses) {
            //存储当前行唯一标识
            excelTeachingClass.setTeachingClassId(index);
            index++;
        }
        //错误日志
        List<Map<String, Object>> errorMapList = new ArrayList<>(excelTeachingClasses.size());
        StringJoiner stringJoiner;
        //拆班教学班分组。常规拆班根据课程分组 单双号拆班根据行政班分组
        Map<String, List<ExcelSubClass>> subClassMap = excelTeachingClasses.stream().collect(Collectors.groupingBy(a -> a.getType() == 1 ? a.getClassNames() : a.getCourseName()));
        for (List<ExcelSubClass> value : subClassMap.values()) {
            //subClass表所需数据
            String uuid = UUID.randomUUID().toString();
            Set<String> classIdsSub = new HashSet<>();
            String classNamesSub = "";
            Set<String> courseIdsSub = new HashSet<>();
            Set<String> courseNamesSub = new HashSet<>();
            String gradeId = "";
            String gradeName = "";
            Integer type = 1;
            for (ExcelSubClass excelTeachingClass : value) {
                type = excelTeachingClass.getType();
                stringJoiner = new StringJoiner("\n");
                Map<String, String> studentObjectMap = formatStudentObject(excelTeachingClass.getStudentObject());
                if (!courseMap.containsKey(excelTeachingClass.getCourseName().trim())) {
                    stringJoiner.add("第" + excelTeachingClass.getTeachingClassId() + "行课程名称不存在:" + excelTeachingClass.getCourseName());
                } else {
                    courseNamesSub.add(excelTeachingClass.getCourseName().trim());
                    courseIdsSub.add(courseMap.get(excelTeachingClass.getCourseName().trim()).getBaseCourseId());
                }
                if (!campusMap.containsKey(excelTeachingClass.getCampusName().trim())) {
                    stringJoiner.add("第" + excelTeachingClass.getTeachingClassId() + "行校区名称不存在:" + excelTeachingClass.getCampusName());
                }
                //判断拆班班级名称是否正确
                if (StrUtil.isBlank(excelTeachingClass.getClassNames())) {
                    stringJoiner.add("第" + excelTeachingClass.getTeachingClassId() + "行拆班班级名称不能为空");
                } else {
                    classNamesSub = StrUtil.isBlank(classNamesSub) ? excelTeachingClass.getClassNames() : classNamesSub;
                    for (String className : excelTeachingClass.getClassNames().split("[,，]")) {
                        className = className.trim();
                        if (!classMap.containsKey(className)) {
                            stringJoiner.add("第" + excelTeachingClass.getTeachingClassId() + "行拆班班级名称称不存在:" + className);
                        } else {
                            classIdsSub.add(classMap.get(className).getClassId());
                            gradeId = StrUtil.isBlank(gradeId) ? classMap.get(className).getGradeId() : gradeId;
                            gradeName = StrUtil.isBlank(gradeName) ? classMap.get(className).getGradeName() : gradeName;
                        }
                    }
                }
                //行政班名转化为行政班id 判断上课对象行政班正确
                String classNames = studentObjectMap.get("classIds");
                if (StrUtil.isNotBlank(classNames)) {
                    for (String className : classNames.split("[,，]")) {
                        className = className.trim();
                        if (!classMap.containsKey(className)) {
                            stringJoiner.add("第" + excelTeachingClass.getTeachingClassId() + "行上课对象行政班名称不存在:" + className);
                        }
                    }
                }
                //待插入教学班对应学生 该行政班学生及改学号学生
                String studentIds = studentObjectMap.get("studentIds");
                if (StrUtil.isNotBlank(studentIds)) {
                    for (String studentId : studentIds.split("[,，]")) {
                        studentId = studentId.trim();
                        if (!studentIdMap.containsKey(studentId)) {
                            stringJoiner.add("第" + excelTeachingClass.getTeachingClassId() + "行学生学号不存在:" + studentId);
                        }
                    }
                }
                //拆班教学班roomId是否存在
                if (StrUtil.isNotBlank(excelTeachingClass.getLectureRoomName()) && !roomMap.containsKey(excelTeachingClass.getLectureRoomName().trim())) {
                    stringJoiner.add("第" + excelTeachingClass.getTeachingClassId() + "行讲授上课场地不存在:" + excelTeachingClass.getLectureRoomName());
                }
                if (StrUtil.isNotBlank(excelTeachingClass.getExperimentalRoomName()) && !roomMap.containsKey(excelTeachingClass.getExperimentalRoomName().trim())) {
                    stringJoiner.add("第" + excelTeachingClass.getTeachingClassId() + "行实验上课场地不存在:" + excelTeachingClass.getExperimentalRoomName());
                }
                if (StrUtil.isNotBlank(excelTeachingClass.getComputerRoomName()) && !roomMap.containsKey(excelTeachingClass.getComputerRoomName())) {
                    stringJoiner.add("第" + excelTeachingClass.getTeachingClassId() + "行上机上课场地不存在:" + excelTeachingClass.getComputerRoomName());
                }
                if (StrUtil.isNotBlank(excelTeachingClass.getOtherRoomName()) && !roomMap.containsKey(excelTeachingClass.getOtherRoomName())) {
                    stringJoiner.add("第" + excelTeachingClass.getTeachingClassId() + "行其他上课场地不存在:" + excelTeachingClass.getOtherRoomName());
                }
                //拆班教学班TeacherNo是否存在
                if (StrUtil.isNotBlank(excelTeachingClass.getLectureTeacherNo()) && !roomMap.containsKey(excelTeachingClass.getLectureTeacherNo().trim())) {
                    stringJoiner.add("第" + excelTeachingClass.getTeachingClassId() + "行讲授任课教师工号不存在:" + excelTeachingClass.getLectureTeacherNo());
                }
                if (StrUtil.isNotBlank(excelTeachingClass.getExperimentalTeacherNo()) && !roomMap.containsKey(excelTeachingClass.getExperimentalTeacherNo().trim())) {
                    stringJoiner.add("第" + excelTeachingClass.getTeachingClassId() + "行实验任课教师工号不存在:" + excelTeachingClass.getExperimentalTeacherNo());
                }
                if (StrUtil.isNotBlank(excelTeachingClass.getComputerTeacherNo()) && !roomMap.containsKey(excelTeachingClass.getComputerTeacherNo())) {
                    stringJoiner.add("第" + excelTeachingClass.getTeachingClassId() + "行上机任课教师工号不存在:" + excelTeachingClass.getComputerTeacherNo());
                }
                if (StrUtil.isNotBlank(excelTeachingClass.getOtherTeacherNo()) && !roomMap.containsKey(excelTeachingClass.getOtherTeacherNo())) {
                    stringJoiner.add("第" + excelTeachingClass.getTeachingClassId() + "行其他任课教师工号不存在:" + excelTeachingClass.getOtherTeacherNo());
                }
                if (stringJoiner.toString().length() == 0) {
                    //行政班名转化为行政班id
                    String classIds = "";
                    if (StrUtil.isNotBlank(classNames)) {
                        for (String className : classNames.split("[,，]")) {
                            className = className.trim();
                            for (ExcelStudent excelStudent : studentClassMap.get(classMap.get(className).getClassId())) {
                                String baseStudentId = excelStudent.getBaseStudentId();
                                //根据学生单双号判断是否添加该学生
                                boolean isAdd = ObjUtil.isNull(excelTeachingClass.getIsSingle()) ||
                                        (int) (baseStudentId.charAt(baseStudentId.length() - 1)) % 2 == excelTeachingClass.getIsSingle() % 2;
                                if (!isAdd) {
                                    teachingClassStudentList.add(new TeachingClassStudent().setTeachingClassId(excelTeachingClass.getTeachingClassId())
                                            .setStudentId(excelStudent.getStudentId())
                                            .setFlag(1));
                                }
                            }
                            classIds += classMap.get(className).getClassName() + ",";
                        }
                    }
                    if (StrUtil.isNotBlank(classIds)) {
                        classIds = classIds.substring(0, classIds.length() - 1);
                    }

                    //待插入教学班
                    teachingClassList.add(new TeachingClass().setTaskId(taskId)
                            .setTeachingClassName(excelTeachingClass.getTeachingClassName())
                            .setCourseId(courseMap.get(excelTeachingClass.getCourseName()).getCourseId())
                            .setCourseName(excelTeachingClass.getCourseName())
                            .setCollegeId(courseMap.get(excelTeachingClass.getCourseName()).getCollegeId())
                            .setToClass(classIds)
                            .setTeachingClassType(0)
                            .setFlag(1)
                            .setStudyNature(courseMap.get(excelTeachingClass.getCourseName()).getStudyNature())
                            .setMajorProp(courseMap.get(excelTeachingClass.getCourseName()).getMajorProp())
                            .setCampusId(campusMap.get(excelTeachingClass.getCampusName()))
                            .setCampusName(excelTeachingClass.getCampusName())
                            .setUniqueShiftSign(uuid)
                            .setIsSingle(excelTeachingClass.getIsSingle())
                            //记录行数作为当前导入唯一标识 用于插入数据库后关联id
                            .setStudentNumber(excelTeachingClass.getTeachingClassId().intValue()));

                    //待插入教学班对应学生 该行政班学生及改学号学生
                    if (StrUtil.isNotBlank(studentIds)) {
                        for (String studentId : studentIds.split("[,，]")) {
                            studentId = studentId.trim();
                            teachingClassStudentList.add(new TeachingClassStudent().setTeachingClassId(excelTeachingClass.getTeachingClassId())
                                    .setStudentId(studentIdMap.get(studentId))
                                    .setFlag(1));

                        }
                    }
                    //待插入教学班参数设置
                    if (StrUtil.isNotBlank(excelTeachingClass.getLectureWeek())) {
                        teachingClassWeekList.add(new TeachingClassWeek().setTeachingClassId(excelTeachingClass.getTeachingClassId())
                                .setWeek(ExcelFormatUtil.toBinary(excelTeachingClass.getLectureWeek(), totalWeek))
                                .setWeekNum(excelTeachingClass.getLectureWeekNum())
                                .setConnectSection(excelTeachingClass.getLectureConnectSection() == null ? 1 : excelTeachingClass.getLectureConnectSection())
                                .setConnectNumber(excelTeachingClass.getLectureConnectNumber() == null ? 0 : excelTeachingClass.getLectureConnectNumber())
                                .setRoomType(excelTeachingClass.getLectureRoomType())
                                .setRoomId(StrUtil.isNotBlank(excelTeachingClass.getLectureRoomName()) ? roomMap.get(excelTeachingClass.getLectureRoomName().trim()) : null)
                                .setHourType(1));
                        //待插入教学班对应教师
                        if (StrUtil.isNotBlank(excelTeachingClass.getLectureTeacherNo())) {
                            for (String teacherNo : excelTeachingClass.getLectureTeacherNo().split("[,，]")) {
                                teacherNo = teacherNo.trim(); // 去除空格
                                teachingClassTeacherList.add(new TeachingClassTeacher().setTeachingClassId(excelTeachingClass.getTeachingClassId())
                                        .setTeacherId(teacherMap.get(teacherNo))
                                                .setHourType(1)
                                        .setTeacherType(0));
                            }
                        }
                    }
                    if (StrUtil.isNotBlank(excelTeachingClass.getExperimentalWeek())) {
                        teachingClassWeekList.add(new TeachingClassWeek().setTeachingClassId(excelTeachingClass.getTeachingClassId())
                                .setWeek(ExcelFormatUtil.toBinary(excelTeachingClass.getExperimentalWeek(), totalWeek))
                                .setWeekNum(excelTeachingClass.getExperimentalWeekNum())
                                .setConnectSection(excelTeachingClass.getExperimentalConnectSection() == null ? 1 : excelTeachingClass.getExperimentalConnectSection())
                                .setConnectNumber(0)
                                .setRoomType(excelTeachingClass.getExperimentalRoomType())
                                .setRoomId(StrUtil.isNotBlank(excelTeachingClass.getExperimentalRoomName()) ? roomMap.get(excelTeachingClass.getExperimentalRoomName().trim()) : null)
                                .setHourType(2));
                        //待插入教学班对应教师
                        if (StrUtil.isNotBlank(excelTeachingClass.getExperimentalTeacherNo())) {
                            for (String teacherNo : excelTeachingClass.getExperimentalTeacherNo().split("[,，]")) {
                                teacherNo = teacherNo.trim(); // 去除空格
                                teachingClassTeacherList.add(new TeachingClassTeacher().setTeachingClassId(excelTeachingClass.getTeachingClassId())
                                        .setTeacherId(teacherMap.get(teacherNo))
                                        .setHourType(2)
                                        .setTeacherType(0));
                            }
                        }
                    }
                    if (StrUtil.isNotBlank(excelTeachingClass.getComputerWeek())) {
                        teachingClassWeekList.add(new TeachingClassWeek().setTeachingClassId(excelTeachingClass.getTeachingClassId())
                                .setWeek(ExcelFormatUtil.toBinary(excelTeachingClass.getComputerWeek(), totalWeek))
                                .setWeekNum(excelTeachingClass.getComputerWeekNum())
                                .setConnectSection(excelTeachingClass.getComputerConnectSection() == null ? 1 : excelTeachingClass.getComputerConnectSection())
                                .setConnectNumber(0)
                                .setRoomType(excelTeachingClass.getComputerRoomType())
                                .setRoomId(StrUtil.isNotBlank(excelTeachingClass.getComputerRoomName()) ? roomMap.get(excelTeachingClass.getComputerRoomName().trim()) : null)
                                .setHourType(3));
                        //待插入教学班对应教师
                        if (StrUtil.isNotBlank(excelTeachingClass.getComputerTeacherNo())) {
                            for (String teacherNo : excelTeachingClass.getComputerTeacherNo().split("[,，]")) {
                                teacherNo = teacherNo.trim(); // 去除空格
                                teachingClassTeacherList.add(new TeachingClassTeacher().setTeachingClassId(excelTeachingClass.getTeachingClassId())
                                        .setTeacherId(teacherMap.get(teacherNo))
                                        .setHourType(3)
                                        .setTeacherType(0));
                            }
                        }
                    }
                    if (StrUtil.isNotBlank(excelTeachingClass.getOtherWeek())) {
                        teachingClassWeekList.add(new TeachingClassWeek().setTeachingClassId(excelTeachingClass.getTeachingClassId())
                                .setWeek(ExcelFormatUtil.toBinary(excelTeachingClass.getOtherWeek(), totalWeek))
                                .setWeekNum(excelTeachingClass.getOtherWeekNum())
                                .setConnectSection(excelTeachingClass.getOtherConnectSection() == null ? 1 : excelTeachingClass.getOtherConnectSection())
                                .setConnectNumber(0)
                                .setRoomType(excelTeachingClass.getOtherRoomType())
                                .setRoomId(StrUtil.isNotBlank(excelTeachingClass.getOtherRoomName()) ? roomMap.get(excelTeachingClass.getOtherRoomName().trim()) : null)
                                .setHourType(4));
                        //待插入教学班对应教师
                        if (StrUtil.isNotBlank(excelTeachingClass.getOtherTeacherNo())) {
                            for (String teacherNo : excelTeachingClass.getOtherTeacherNo().split("[,，]")) {
                                teacherNo = teacherNo.trim(); // 去除空格
                                teachingClassTeacherList.add(new TeachingClassTeacher().setTeachingClassId(excelTeachingClass.getTeachingClassId())
                                        .setTeacherId(teacherMap.get(teacherNo))
                                        .setHourType(4)
                                        .setTeacherType(0));
                            }
                        }
                    }
                } else {
                    Map<String, Object> errorMap = new LinkedHashMap<>(2);
                    errorMap.put("原Excel行号", index);
                    errorMap.put("错误原因", stringJoiner.toString());
                    errorMapList.add(errorMap);
                }
            }
            //构造subClass数据
            subClassList.add(new SubClass().setTaskId(taskId)
                    .setClassId(CollUtil.join(classIdsSub, ","))
                    .setClassName(classNamesSub)
                    .setCourseId(CollUtil.join(courseIdsSub, ","))
                    .setCourseName(CollUtil.join(courseNamesSub, ","))
                    .setGradeId(gradeId)
                    .setGradeName(gradeName)
                    .setUniqueShiftSign(uuid)
                    .setType(type));
        }
        //返回实体类
        FileImportInfo fileImportInfo = FileImportInfo.builder()
                .errorImportFilePath("")
                .failureImportNum(errorMapList.size())
                .successImportNum(excelTeachingClasses.size() - errorMapList.size())
                .build();
        if (errorMapList.size() > 0) {
            String storePath = "/" + taskInfo.getTaskName() + "/导入分班教学班错误信息-" + LocalDate.now() + ".xlsx";
            String targetPath = GlobalConstant.OUTPUT_EXCEL_PATH + storePath;

            FileUtil.del(targetPath);
            ExcelWriter writer = ExcelUtil.getWriter(targetPath, "导入教学班错误信息");
            writer.write(errorMapList, true);
            writer.close();
            fileImportInfo.setErrorImportFilePath(GlobalConstant.ACCESS_PATH + "/static/OutputExcel" + storePath);
        }
        //插入教学班
        if (CollUtil.isNotEmpty(subClassList) && CollUtil.isNotEmpty(teachingClassList) && CollUtil.isNotEmpty(teachingClassStudentList) && CollUtil.isNotEmpty(teachingClassWeekList)) {
            batchInsert(taskId, teachingClassList, teachingClassTeacherList, teachingClassStudentList, teachingClassWeekList, subClassList);
        }
        return fileImportInfo;
    }


    /**
     * 批量插入数据库
     *
     * @param taskId
     * @param teachingClassList
     * @param teachingClassTeacherList
     * @param teachingClassStudentList
     * @param teachingClassWeekList
     */
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public void batchInsert(Integer taskId, List<TeachingClass> teachingClassList, List<TeachingClassTeacher> teachingClassTeacherList, List<TeachingClassStudent> teachingClassStudentList, List<TeachingClassWeek> teachingClassWeekList, List<SubClass> subClassList) {
        //先删掉原来的教学班相关信息
        if (CollUtil.isEmpty(subClassList)){
            List<Long> teachingClassIds = this.lambdaQuery().eq(TeachingClass::getTaskId, taskId).eq(TeachingClass::getFlag, 1).ne(TeachingClass::getTeachingClassType, 3).list()
                    .stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
            deleteClass(teachingClassIds);
        }
        teachingClassMapper.addBatch(teachingClassList);
        Map<Long, Long> teachingClassIdMap = teachingClassList.stream().collect(Collectors.toMap(teachingClass -> teachingClass.getStudentNumber().longValue(), TeachingClass::getTeachingClassId));
        teachingClassStudentList.forEach(teachingClassStudent -> teachingClassStudent.setTeachingClassId(teachingClassIdMap.get(teachingClassStudent.getTeachingClassId())));
        teachingClassTeacherList.forEach(teachingClassTeacher -> teachingClassTeacher.setTeachingClassId(teachingClassIdMap.get(teachingClassTeacher.getTeachingClassId())));
        teachingClassWeekList.forEach(teachingClassWeek -> teachingClassWeek.setTeachingClassId(teachingClassIdMap.get(teachingClassWeek.getTeachingClassId())));
        //插入老师
        Consumer<List<TeachingClassTeacher>> teacherConsumer = o -> teachingClassTeacherMapper.addBatch(o);
        BatchInsert.batchSplitInsert(teachingClassTeacherList, teacherConsumer);
        //批量插入教学班学生，大数据批量插入
        Consumer<List<TeachingClassStudent>> studentConsumer = o -> teachingClassStudentMapper.addBatch(o);
        BatchInsert.batchSplitInsert(teachingClassStudentList, studentConsumer);
        //插入教学班参数
        Consumer<List<TeachingClassWeek>> weekConsumer = o -> teachingClassWeekMapper.addBatch(o);
        BatchInsert.batchSplitInsert(teachingClassWeekList, weekConsumer);
        //插入分班数据 SubClass
        if (CollUtil.isNotEmpty(subClassList)) {
            subClassMapper.delete(new LambdaQueryWrapper<SubClass>().eq(SubClass::getTaskId, taskId));
            subClassMapper.addBatch(subClassList);
        }
    }


    /**
     * 将上课对象转化为学生 行政班字符串
     *
     * @param studentObject
     * @return
     */
    public Map<String, String> formatStudentObject(String studentObject) {
        Map<String, String> result = new HashMap<>();
        result.put("studentIds", "");
        result.put("classIds", "");
        String[] parts = studentObject.split(";");
        for (String part : parts) {
            String[] subParts = part.split("\\|");
            if (subParts.length == 2) {
                String type = subParts[0];
                String values = subParts[1];
                if ("C".equals(type)) {
                    result.put("classIds", values);
                } else if ("S".equals(type)) {
                    result.put("studentIds", values);
                }
            }
        }
        return result;
    }


    /**
     * 读取excel 返回教学班信息
     *
     * @param file
     * @return
     */
    public List<ExcelTeachingClass> readExcel(MultipartFile file) {
        List<ExcelTeachingClass> excelTeachingClasses = new ArrayList<>();
        List<String> expectedHeaders = Arrays.asList(
                "教学班名称", "课程名称", "上课对象", "学生单双号", "任课教师工号", "修读性质", "安排教室范围", "校区", "是否拆班",
                "讲授开课周", "讲授周学时", "讲授连上节次", "连上次数", "讲授场地类型",
                "实验开课周", "实验周学时", "实验连上节次", "实验场地类型",
                "上机开课周", "上机周学时", "上机连上节次", "上机场地类型",
                "其他开课周", "其他周学时", "其他连上节次", "其他场地类型");
        try {
            InputStream inputStream = file.getResource().getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream, 0);
            //读取表头 判断是否符合预期
            List<String> actualHeaders = reader.readRow(1).stream()
                    .map(Object::toString).collect(Collectors.toList());
            if (!expectedHeaders.equals(actualHeaders)) {
                throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
            }

            reader.addHeaderAlias("教学班名称", "teachingClassName");
            reader.addHeaderAlias("课程名称", "courseName");
            reader.addHeaderAlias("上课对象", "studentObject");
            reader.addHeaderAlias("学生单双号", "isSingle");
            reader.addHeaderAlias("任课教师工号", "teacherNo");
            reader.addHeaderAlias("修读性质", "studyNature");
            reader.addHeaderAlias("安排教室范围", "roomName");
            reader.addHeaderAlias("校区", "campusName");
            reader.addHeaderAlias("是否拆班", "uniqueShiftSign");
            reader.addHeaderAlias("讲授开课周", "lectureWeek");
            reader.addHeaderAlias("讲授周学时", "lectureWeekNum");
            reader.addHeaderAlias("讲授连上节次", "lectureConnectSection");
            reader.addHeaderAlias("连上次数", "lectureConnectNumber");
            reader.addHeaderAlias("讲授场地类型", "lectureRoomType");
            reader.addHeaderAlias("实验开课周", "experimentalWeek");
            reader.addHeaderAlias("实验周学时", "experimentalWeekNum");
            reader.addHeaderAlias("实验连上节次", "experimentalConnectSection");
            reader.addHeaderAlias("实验场地类型", "experimentalRoomType");
            reader.addHeaderAlias("上机开课周", "computerWeek");
            reader.addHeaderAlias("上机周学时", "computerWeekNum");
            reader.addHeaderAlias("上机连上节次", "computerConnectSection");
            reader.addHeaderAlias("上机场地类型", "computerRoomType");
            reader.addHeaderAlias("其他开课周", "otherWeek");
            reader.addHeaderAlias("其他周学时", "otherWeekNum");
            reader.addHeaderAlias("其他连上节次", "otherConnectSection");
            reader.addHeaderAlias("其他场地类型", "otherRoomType");
            excelTeachingClasses = reader.read(1, 2, ExcelTeachingClass.class);
            reader.close();
        } catch (IOException e) {
            log.info("excel导入教学任务失败:{}", e.getMessage());
        }
        if (excelTeachingClasses.size() == 0) {
            throw new BizException(5, "导入数据为空，请检查后重新导入");
        }
        return excelTeachingClasses;
    }
    public List<ExcelTeachingClassAll> readExcelAll(MultipartFile file) {
        List<ExcelTeachingClassAll> excelTeachingClasses = new ArrayList<>();
        List<String> expectedHeaders = Arrays.asList(
                "教学班名称", "课程名称", "上课对象", "修读性质", "校区",
                "讲授开课周", "讲授周学时", "讲授连上节次", "讲授连上次数", "讲授场地类型","讲授上课场地(一个)","讲授教师",
                "实验开课周", "实验周学时", "实验连上节次", "实验连上次数", "实验场地类型","实验上课场地(一个)","实验教师",
                "上机开课周", "上机周学时", "上机连上节次", "上机连上次数", "上机场地类型","上机上课场地(一个)","上机教师",
                "其他开课周", "其他周学时", "其他连上节次", "其他连上次数", "其他场地类型","其他上课场地(一个)","其他教师");
        try {
            InputStream inputStream = file.getResource().getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream, 0);
            //读取表头 判断是否符合预期
            List<String> actualHeaders = reader.readRow(1).stream()
                    .map(Object::toString).collect(Collectors.toList());
            if (!expectedHeaders.equals(actualHeaders)) {
                throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
            }

            reader.addHeaderAlias("教学班名称", "teachingClassName");
            reader.addHeaderAlias("课程名称", "courseName");
            reader.addHeaderAlias("上课对象", "studentObject");
            reader.addHeaderAlias("修读性质", "studyNature");
            reader.addHeaderAlias("校区", "campusName");
            reader.addHeaderAlias("讲授开课周", "lectureWeek");
            reader.addHeaderAlias("讲授周学时", "lectureWeekNum");
            reader.addHeaderAlias("讲授连上节次", "lectureConnectSection");
            reader.addHeaderAlias("讲授连上次数", "lectureConnectNumber");
            reader.addHeaderAlias("讲授场地类型", "lectureRoomType");
            reader.addHeaderAlias("讲授上课场地(一个)", "lectureRoomName");
            reader.addHeaderAlias("讲授教师", "lectureTeacher");

            reader.addHeaderAlias("实验开课周", "experimentalWeek");
            reader.addHeaderAlias("实验周学时", "experimentalWeekNum");
            reader.addHeaderAlias("实验连上节次", "experimentalConnectSection");
            reader.addHeaderAlias("实验场地类型", "experimentalRoomType");
            reader.addHeaderAlias("实验连上次数", "experimentalConnectNumber");
            reader.addHeaderAlias("实验上课场地(一个)", "experimentalRoomName");
            reader.addHeaderAlias("实验教师", "experimentalTeacher");

            reader.addHeaderAlias("上机开课周", "computerWeek");
            reader.addHeaderAlias("上机周学时", "computerWeekNum");
            reader.addHeaderAlias("上机连上节次", "computerConnectSection");
            reader.addHeaderAlias("上机场地类型", "computerRoomType");
            reader.addHeaderAlias("上机连上次数", "computerConnectNumber");
            reader.addHeaderAlias("上机上课场地(一个)", "computerRoomName");
            reader.addHeaderAlias("上机教师", "computerTeacher");

            reader.addHeaderAlias("其他开课周", "otherWeek");
            reader.addHeaderAlias("其他周学时", "otherWeekNum");
            reader.addHeaderAlias("其他连上节次", "otherConnectSection");
            reader.addHeaderAlias("其他场地类型", "otherRoomType");
            reader.addHeaderAlias("其他连上次数", "otherConnectNumber");
            reader.addHeaderAlias("其他上课场地(一个)", "otherRoomName");
            reader.addHeaderAlias("其他教师", "otherTeacher");

            excelTeachingClasses = reader.read(1, 2, ExcelTeachingClassAll.class);
            reader.close();
        } catch (IOException e) {
            log.info("excel导入教学任务失败:{}", e.getMessage());
        }
        if (excelTeachingClasses.size() == 0) {
            throw new BizException(5, "导入数据为空，请检查后重新导入");
        }
        return excelTeachingClasses;
    }

    /**
     * 读取拆班excel 返回教学班信息
     *
     * @param file
     * @return
     */
    public List<ExcelSubClass> readSubClassExcel(MultipartFile file) {
        List<ExcelSubClass> excelTeachingClasses = new ArrayList<>();
        List<String> expectedHeaders = Arrays.asList(
                "教学班名称", "课程名称", "拆班类型", "拆班班级名称", "上课对象", "学生单双号", "校区",
                "讲授开课周", "讲授周学时", "讲授连上节次", "讲授连上次数", "讲授场地类型", "讲授上课场地","讲授任课教师工号",
                "实验开课周", "实验周学时", "实验连上节次", "实验连上次数", "实验场地类型", "实验上课场地","实验任课教师工号",
                "上机开课周", "上机周学时", "上机连上节次", "上机连上次数", "上机场地类型", "上机上课场地","上机任课教师工号",
                "其他开课周", "其他周学时", "其他连上节次", "其他连上次数", "其他场地类型", "其他上课场地","其他任课教师工号");
        try {
            InputStream inputStream = file.getResource().getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream, 0);
            //读取表头 判断是否符合预期
            List<String> actualHeaders = reader.readRow(1).stream()
                    .map(Object::toString).collect(Collectors.toList());
            if (!expectedHeaders.equals(actualHeaders)) {
                throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
            }

            reader.addHeaderAlias("教学班名称", "teachingClassName");
            reader.addHeaderAlias("课程名称", "courseName");
            reader.addHeaderAlias("拆班类型", "type");
            reader.addHeaderAlias("拆班班级名称", "classNames");
            reader.addHeaderAlias("上课对象", "studentObject");
            reader.addHeaderAlias("学生单双号", "isSingle");
            reader.addHeaderAlias("校区", "campusName");

            reader.addHeaderAlias("讲授开课周", "lectureWeek");
            reader.addHeaderAlias("讲授周学时", "lectureWeekNum");
            reader.addHeaderAlias("讲授连上节次", "lectureConnectSection");
            reader.addHeaderAlias("讲授连上次数", "lectureConnectNumber");
            reader.addHeaderAlias("讲授场地类型", "lectureRoomType");
            reader.addHeaderAlias("讲授上课场地", "lectureRoomName");
            reader.addHeaderAlias("讲授任课教师工号", "lectureTeacherNo");

            reader.addHeaderAlias("实验开课周", "experimentalWeek");
            reader.addHeaderAlias("实验周学时", "experimentalWeekNum");
            reader.addHeaderAlias("实验连上节次", "experimentalConnectSection");
            reader.addHeaderAlias("实验连上次数", "experimentalConnectNumber");
            reader.addHeaderAlias("实验场地类型", "experimentalRoomType");
            reader.addHeaderAlias("实验上课场地", "experimentalRoomName");
            reader.addHeaderAlias("实验任课教师工号", "experimentalTeacherNo");

            reader.addHeaderAlias("上机开课周", "computerWeek");
            reader.addHeaderAlias("上机周学时", "computerWeekNum");
            reader.addHeaderAlias("上机连上节次", "computerConnectSection");
            reader.addHeaderAlias("上机连上次数", "computerConnectNumber");
            reader.addHeaderAlias("上机场地类型", "computerRoomType");
            reader.addHeaderAlias("上机上课场地", "computerRoomName");
            reader.addHeaderAlias("上机任课教师工号", "computerTeacherNo");

            reader.addHeaderAlias("其他开课周", "otherWeek");
            reader.addHeaderAlias("其他周学时", "otherWeekNum");
            reader.addHeaderAlias("其他连上节次", "otherConnectSection");
            reader.addHeaderAlias("其他连上次数", "otherConnectNumber");
            reader.addHeaderAlias("其他场地类型", "otherRoomType");
            reader.addHeaderAlias("其他上课场地", "otherRoomName");
            reader.addHeaderAlias("其他任课教师工号", "otherTeacherNo");

            excelTeachingClasses = reader.read(1, 2, ExcelSubClass.class);
            reader.close();
        } catch (IOException e) {
            log.info("excel导入教学任务失败:{}", e.getMessage());
        }
        if (excelTeachingClasses.size() == 0) {
            throw new BizException(5, "导入数据为空，请检查后重新导入");
        }
        return excelTeachingClasses;
    }


}
